Loading...
Loading...
Better Auth — framework-agnostic TypeScript authentication & authorization library. Covers setup, email/password, social OAuth (40+ providers), passkeys, magic links, 2FA, organizations, sessions, plugins, admin, hooks, and security hardening. Use when implementing auth with Better Auth: configuring auth instances, adding providers, setting up database adapters (Prisma, Drizzle, PostgreSQL, MySQL, SQLite, MongoDB), integrating with frameworks (Next.js, Nuxt, SvelteKit, Astro, Hono, Express, Elysia, Fastify, Expo), managing sessions, or extending with plugins.
npx skill4agent add fellipeutaka/leon better-authnpm install better-auth| Package | Use case |
|---|---|
| WebAuthn/Passkey auth |
| SAML/OIDC enterprise SSO |
| Stripe payments |
| React Native/Expo |
BETTER_AUTH_SECRET=<32+ chars, generate: openssl rand -base64 32>
BETTER_AUTH_URL=http://localhost:3000
DATABASE_URL=<connection string>lib/auth.tsimport { betterAuth } from "better-auth";
export const auth = betterAuth({
database: process.env.DATABASE_URL, // or adapter instance
emailAndPassword: { enabled: true },
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
},
},
plugins: [], // add plugins here
});
export type Session = typeof auth.$Infer.Session;lib/auth-client.tsimport { createAuthClient } from "better-auth/react"; // or /vue, /svelte, /solid, /client
export const authClient = createAuthClient({
plugins: [], // add client plugins here
});| Framework | File | Handler |
|---|---|---|
| Next.js App Router | | |
| Next.js Pages | | |
| Express | any | |
| Hono | route | |
| SvelteKit | | |
| Astro | | |
| Elysia | plugin | |
npx @better-auth/cli@latest migrate # Apply schema (built-in adapter)
npx @better-auth/cli@latest generate # Generate for Prisma/Drizzle
npx @better-auth/cli@latest generate --output prisma/schema.prisma
npx @better-auth/cli@latest generate --output src/db/auth-schema.tsauthauthClientuseSessionsignInsignUpsignOutauth.$Infer.Sessionauth.$Infer.Session.usercreateAuthClient<typeof auth>()| Method | Package | Config/Plugin | Reference |
|---|---|---|---|
| Email/Password | built-in | | authentication.md |
| Social OAuth | built-in | | authentication.md |
| Magic Link | built-in | | authentication.md |
| Passkey | | | authentication.md |
| Username | built-in | | authentication.md |
| Email OTP | built-in | | authentication.md |
| Phone Number | built-in | | authentication.md |
| Anonymous | built-in | | authentication.md |
import { twoFactor } from "better-auth/plugins/two-factor"from "better-auth/plugins"| Plugin | Server Import | Client Import | Purpose |
|---|---|---|---|
| | | TOTP, OTP, backup codes |
| | | Multi-tenant orgs, teams, RBAC |
| | | User management, impersonation |
| | | WebAuthn/FIDO2 |
| | | Passwordless email links |
| | | Email one-time passwords |
| | | Username-based auth |
| | | Phone-based auth |
| | | Guest sessions |
| | | API key management |
| | — | Bearer token auth |
| | | JWT tokens |
| | | Multiple active sessions |
| | — | Become OAuth provider |
| | — | Become OIDC provider |
| | | SAML/OIDC enterprise SSO |
| | — | API documentation |
| | — | Extend session data |
| | | Custom OAuth providers |
| | | Google One Tap |
auth({ plugins: [...] })createAuthClient({ plugins: [...] })| Adapter | Setup |
|---|---|
| SQLite | Pass |
| PostgreSQL | Pass |
| MySQL | Pass |
| Prisma | |
| Drizzle | |
| MongoDB | |
| Connection string | |
UserusersmodelName: "user"usersessionaccountverificationsession: {
expiresIn: 60 * 60 * 24 * 7, // 7 days (default)
updateAge: 60 * 60 * 24, // refresh every 24h (default)
freshAge: 60 * 60 * 24, // require re-auth after 24h for sensitive ops
cookieCache: {
enabled: true,
maxAge: 300, // 5 min
strategy: "compact", // "compact" | "jwt" | "jwe"
},
}secondaryStoragecustomSession| DO | DON'T |
|---|---|
| Use 32+ char secret with high entropy | Commit secrets to version control |
Set | Disable CSRF check ( |
Configure | Disable origin check |
| Enable rate limiting (on by default in prod) | Use |
Configure | Skip email verification setup |
Use | Store OAuth tokens unencrypted if used for API calls |
Set | Return specific error messages ("user not found") |
session.storeSessionInDatabase: true"/api/auth/*splat""/api/auth/*"nextCookies()| Issue | Fix |
|---|---|
| "Secret not set" | Add |
| "Invalid Origin" | Add domain to |
| Cookies not setting | Check |
| OAuth callback errors | Verify redirect URIs in provider dashboard match exactly |
| Type errors after adding plugin | Re-run CLI generate/migrate |
| Session null in RSC | Add |
| 2FA redirect not working | Add |
| File | When to read |
|---|---|
| setup.md | Setting up new project, configuring DB, route handlers |
| authentication.md | Implementing any auth method (email, social, passkey, magic link, etc.) |
| sessions.md | Configuring session expiry, caching, stateless mode, secondary storage |
| security.md | Hardening for production — rate limiting, CSRF, cookies, OAuth security |
| plugins.md | Using or creating plugins, plugin catalog |
| framework-integrations.md | Framework-specific setup (Next.js, Nuxt, SvelteKit, Hono, Express, etc.) |
| two-factor.md | Implementing 2FA (TOTP, OTP, backup codes, trusted devices) |
| organizations.md | Multi-tenant orgs, teams, invitations, RBAC |
| admin.md | User management, roles, banning, impersonation |
| hooks-and-middleware.md | Custom logic via before/after hooks, DB hooks, middleware |