Files
cfw-auth/docs/better-auth-plugin-compass.md
imeepos e3057928a2 feat: add better authentication features and organization management
- 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.
2026-06-10 19:39:15 -07:00

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-auth and node_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:

  • openAPI
  • i18n
  • haveIBeenPwned
  • emailOTP
  • twoFactor
  • multiSession
  • lastLoginMethod
  • admin
  • username
  • phoneNumber
  • organization
  • apiKey
  • expo

Conditional runtime plugins:

  • captcha, when CAPTCHA_PROVIDER=cloudflare-turnstile and CAPTCHA_SECRET_KEY are set
  • genericOAuth, when generic OAuth provider env vars are set
  • passkey, when PASSKEY_RP_ID, PASSKEY_RP_NAME, and PASSKEY_ORIGIN are set
  • jwt, when ENABLE_JWT=true
  • bearer, when ENABLE_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 run pnpm db:check.
  • Keep conditional runtime plugins represented in src/auth.migration.ts when they can affect schema or generated API shape.
  • Do not treat jwt as a session replacement. Use it for services that need JWT/JWKS, and keep cookie sessions as the normal browser auth path.
  • Use bearer only for clients that must send bearer tokens to auth endpoints. It widens token-acceptance behavior.
  • Keep captcha on high-abuse endpoints such as email sign-up, email sign-in, and password reset. Turnstile secrets belong in Worker secrets.
  • Keep genericOAuth provider config behind env and avoid hard-coding enterprise IdP details.
  • Treat organization as 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, and i18n are auth-flow protection and presentation edges.
  • genericOAuth, passkey, phoneNumber, and emailOTP are identity proof adapters.
  • jwt, bearer, and apiKey are machine/API access edges.
  • expo is 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.