- Introduced new database migration for enhanced user and organization management. - Updated package dependencies to include new Better Auth modules for API keys, Expo, and i18n. - Implemented SMS functionality for phone verification and password resets. - Enhanced authentication plugins with username and phone number support. - Added performance configuration options for session cookie caching and API key updates. - Updated email templates to include organization invitation messages. - Improved testing coverage for new features and configurations.
6.0 KiB
Better Auth Plugin Compass
This note is the project-level compass for choosing Better Auth plugins. It combines the current official plugin ecosystem, installed package evidence, and cfw-auth's Cloudflare/D1 constraints.
Source Baseline
- Better Auth official plugin overview, v1.6:
https://better-auth.com/docs/plugins - Better Auth plugin mechanism docs:
https://better-auth.com/docs/concepts/plugins - Official plugin pages for 2FA, passkey, organization, API key, JWT, Stripe, and community plugins
- Installed package type definitions under
node_modules/better-authandnode_modules/@better-auth/* - Local runtime config:
src/plugins.ts - Local schema-generation config:
src/auth.migration.ts
Important rule: official docs establish product intent; installed package types establish the exact API shape this repo can compile against.
Ecosystem Map
| Category | Plugins | Primary use |
|---|---|---|
| Login and identity proof | twoFactor, passkey, magicLink, emailOTP, phoneNumber, anonymous, username, oneTap, siwe, genericOAuth, multiSession, lastLoginMethod |
Human authentication, passwordless flows, account recovery, session UX |
| Authorization and management | admin, organization, sso, scim |
Admin controls, B2B tenants, enterprise SSO, directory sync |
| API, token, and machine access | agentAuth, apiKey, jwt, bearer, oneTimeToken, oauthProxy |
API clients, service access, token exchange, agent flows |
| Identity-provider surface | oauthProvider, oidcProvider, mcp, deviceAuthorization |
Turning the app into an OAuth/OIDC/MCP identity provider |
| Billing and entitlement | stripe, polar, autumn, creem, dodopayments, commet |
Subscription, checkout, seats, usage-based pricing |
| Security and operations | captcha, haveIBeenPwned, i18n, openAPI, testUtils |
Abuse prevention, password safety, localized errors, docs, tests |
| Analytics and tracking | dub |
Lead tracking and OAuth/link attribution |
Community plugins are useful for ecosystem gaps such as LDAP, audit logs, Firebase Auth, payment providers, wallet chains, university email checks, or devtools. Treat them as third-party code: review maintenance, schema changes, runtime compatibility, and test coverage before adopting them.
cfw-auth Current Plugin Set
Default runtime plugins:
openAPIi18nhaveIBeenPwnedemailOTPtwoFactormultiSessionlastLoginMethodadminusernamephoneNumberorganizationapiKeyexpo
Conditional runtime plugins:
captcha, whenCAPTCHA_PROVIDER=cloudflare-turnstileandCAPTCHA_SECRET_KEYare setgenericOAuth, when generic OAuth provider env vars are setpasskey, whenPASSKEY_RP_ID,PASSKEY_RP_NAME, andPASSKEY_ORIGINare setjwt, whenENABLE_JWT=truebearer, whenENABLE_BEARER=true
Migration-only static config must include every plugin that can affect schema or generated endpoint metadata. In this repo that means src/auth.migration.ts intentionally includes dummy config for conditional plugins. The important schema-bearing addition is jwt, which creates the jwks table.
Usage Patterns
Server config:
import { betterAuth } from "better-auth";
import { i18n } from "@better-auth/i18n";
import { passkey } from "@better-auth/passkey";
import { jwt, organization, twoFactor } from "better-auth/plugins";
export const auth = betterAuth({
database: env.DB,
plugins: [
i18n({
translations: {
en: {},
zh: { USER_NOT_FOUND: "用户不存在。" },
},
detection: ["header", "cookie"],
}),
organization(),
twoFactor(),
passkey(),
jwt(),
],
});
Client config, when a plugin exposes a client plugin:
import { createAuthClient } from "better-auth/client";
import { i18nClient } from "@better-auth/i18n/client";
import { twoFactorClient } from "better-auth/client/plugins";
export const authClient = createAuthClient({
plugins: [
i18nClient(),
twoFactorClient(),
],
});
Best Practices
- Choose plugins from workflow pressure, not from the catalog. Every plugin can add endpoints, hooks, schema, client actions, and security review surface.
- Keep server and client plugin choices paired. Some server plugins need a matching client plugin for typed client actions.
- After changing schema-affecting plugins, run
pnpm db:generate, inspect SQL, then runpnpm db:check. - Keep conditional runtime plugins represented in
src/auth.migration.tswhen they can affect schema or generated API shape. - Do not treat
jwtas a session replacement. Use it for services that need JWT/JWKS, and keep cookie sessions as the normal browser auth path. - Use
beareronly for clients that must send bearer tokens to auth endpoints. It widens token-acceptance behavior. - Keep
captchaon high-abuse endpoints such as email sign-up, email sign-in, and password reset. Turnstile secrets belong in Worker secrets. - Keep
genericOAuthprovider config behind env and avoid hard-coding enterprise IdP details. - Treat
organizationas the tenant boundary. App tables should consume organization/member projections rather than becoming a second source of auth truth. - Keep API keys hashed, named, prefixed, scoped, and revocable. Organization-owned keys are better for shared integrations.
- Review community plugins like any third-party dependency: schema, hooks, secrets, runtime assumptions, release activity, and tests.
Simplicity Boundary
The stable core for this project is:
User + Session + Identifier + Organization + Membership + API Key
Everything else is an edge capability:
captcha,haveIBeenPwned, andi18nare auth-flow protection and presentation edges.genericOAuth,passkey,phoneNumber, andemailOTPare identity proof adapters.jwt,bearer, andapiKeyare machine/API access edges.expois client runtime integration.
Do not move billing, enterprise SSO, SCIM, MCP provider, or OAuth/OIDC provider concerns into the core until a real caller needs them.