关于 better-auth
面向多种框架的 TypeScript 身份验证库,采用插件架构。它支持多种认证方式和数据库适配器,并提供框架对应的客户端与服务端集成。
主要功能
- 01邮箱与社交账号认证
- 02通行密钥、OTP 与魔法链接
- 03基于插件扩展认证能力
- 04框架对应的客户端和服务端配置
- 05多种数据库适配器
- 06会话与安全配置
适用场景
- 01为 TypeScript 应用添加身份验证
- 02启用通行密钥或双重验证登录
- 03配置组织角色与团队
- 04跨框架配置会话
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ marcioaltoe/ skills --skill better-auth安装后在 Claude Code 中输入/better-auth确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/admin.mdauthentication.mdframework-integrations.mdhooks-and-middleware.mdorganizations.mdplugins.mdsecurity.mdsessions.mdsetup.mdtwo-factor.md详细介绍
Better Auth
与框架无关的 TypeScript 身份验证库。采用基于插件的架构,支持 40 多种 OAuth 提供商和 18 种以上的框架集成。
快速开始
安装
npm install better-auth
按需安装作用域包:
| 包 | 用途 |
|---|---|
@better-auth/passkey | WebAuthn/Passkey 身份验证 |
@better-auth/sso | SAML/OIDC 企业 SSO |
@better-auth/stripe | Stripe 支付 |
@better-auth/expo | 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.ts)
import { 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.ts)
import { createAuthClient } from "better-auth/react"; // or /vue, /svelte, /solid, /client
export const authClient = createAuthClient({
plugins: [], // add client plugins here
});
路由处理程序
| 框架 | 文件 | 处理程序 |
|---|---|---|
| Next.js App Router | app/api/auth/[...all]/route.ts | toNextJsHandler(auth)`` → 导出 { GET, POST }` |
| Next.js Pages | pages/api/auth/[...all].ts | toNextJsHandler(auth) → 默认导出 |
| Express | 任意 | app.all("/api/auth/*splat", toNodeHandler(auth)) |
| Hono | 路由 | app.on(["POST","GET"], "/api/auth/**", (c) => auth.handler(c.req.raw)) |
| SvelteKit | hooks.server.ts | svelteKitHandler({ auth, event }) |
| Astro | pages/api/auth/[...all].ts | toAstroHandler(auth) |
| Elysia | 插件 | new Elysia().mount(auth.handler) |
所有框架请参阅 references/framework-integrations.md。
CLI 命令
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.ts
添加或更改插件后请重新运行。
核心概念
- 服务端实例(
auth):处理所有身份验证逻辑、数据库和会话 - 客户端实例(
authClient):特定于框架的钩子(useSession、signIn、signUp、signOut) - 插件:扩展服务端和客户端,可添加端点、数据库表和钩子
- 类型推断:使用
auth.$Infer.Session、auth.$Infer.Session.user实现完整的类型安全 - 对于分离的客户端和服务端项目:
createAuthClient<typeof auth>()
身份验证方式
| 方式 | 包 | 配置/插件 | 参考 |
|---|---|---|---|
| 邮箱/密码 | 内置 | emailAndPassword: { enabled: true } | authentication.md |
| 社交 OAuth | 内置 | socialProviders: { google: {...} } | authentication.md |
| Magic Link | 内置 | magicLink() 插件 | authentication.md |
| Passkey | @better-auth/passkey | passkey() 插件 | authentication.md |
| 用户名 | 内置 | username() 插件 | authentication.md |
| 邮箱 OTP | 内置 | emailOtp() 插件 | authentication.md |
| 电话号码 | 内置 | phoneNumber() 插件 | authentication.md |
| 匿名身份验证 | 内置 | anonymous() 插件 | authentication.md |
插件快速参考
从专用路径导入以进行摇树优化:import { twoFactor } from "better-auth/plugins/two-factor",而不是 from "better-auth/plugins"。
| 插件 | 服务端导入 | 客户端导入 | 用途 |
|---|---|---|---|
twoFactor | better-auth/plugins/two-factor | twoFactorClient | TOTP、OTP、备用代码 |
organization | better-auth/plugins/organization | organizationClient | 多租户组织、团队、RBAC |
admin | better-auth/plugins/admin | adminClient | 用户管理、身份模拟 |
passkey | @better-auth/passkey | passkeyClient | WebAuthn/FIDO2 |
magicLink | better-auth/plugins/magic-link | magicLinkClient | 无密码电子邮件链接 |
emailOtp | better-auth/plugins/email-otp | emailOtpClient | 电子邮件一次性密码 |
username | better-auth/plugins/username | usernameClient | 基于用户名的身份验证 |
phoneNumber | better-auth/plugins/phone-number | phoneNumberClient | 基于电话号码的身份验证 |
anonymous | better-auth/plugins/anonymous | anonymousClient | 访客会话 |
apiKey | better-auth/plugins/api-key | apiKeyClient | API 密钥管理 |
bearer | better-auth/plugins/bearer | — | Bearer 令牌身份验证 |
jwt | better-auth/plugins/jwt | jwtClient | JWT 令牌 |
multiSession | better-auth/plugins/multi-session | multiSessionClient | 多个活动会话 |
oauthProvider | better-auth/plugins/oauth-provider | — | 成为 OAuth 提供方 |
oidcProvider | better-auth/plugins/oidc-provider | — | 成为 OIDC 提供方 |
sso | @better-auth/sso | ssoClient | SAML/OIDC 企业 SSO |
openAPI | better-auth/plugins/open-api | — | API 文档 |
customSession | better-auth/plugins/custom-session | — | 扩展会话数据 |
genericOAuth | better-auth/plugins/generic-oauth | genericOAuthClient | 自定义 OAuth 提供方 |
oneTap | better-auth/plugins/one-tap | oneTapClient | Google One Tap |
模式:在 auth({ plugins: [...] }) 中添加服务端插件 + 在 createAuthClient({ plugins: [...] }) 中添加客户端插件 + 重新运行 CLI 迁移。
详细用法和自定义插件创建方法,请参阅 references/plugins.md。
数据库设置
| 适配器 | 设置 |
|---|---|
| SQLite | 传入 better-sqlite3 或 bun:sqlite 实例 |
| PostgreSQL | 传入 pg.Pool 实例 |
| MySQL | 传入 mysql2 连接池 |
| Prisma | 从 better-auth/adapters/prisma 导入 prismaAdapter(prisma, { provider: "postgresql" }) |
| Drizzle | 从 better-auth/adapters/drizzle 导入 drizzleAdapter(db, { provider: "pg" }) |
| MongoDB | 从 better-auth/adapters/mongodb 导入 mongodbAdapter(db) |
| 连接字符串 | database: process.env.DATABASE_URL(使用内置 Kysely) |
重要: 配置使用 ORM 模型名称,而非数据库表名。Prisma 模型 User 映射到表 users 时 → 使用 modelName: "user"。
核心架构表:user、session、account、verification。插件会添加各自的表。
完整的数据库设置详情,请参阅 references/setup.md。
会话管理
关键选项:
session: {
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"
},
}
secondaryStorage(Redis/KV):默认将会话存储在其中,而非数据库- 无状态模式:无数据库 + cookieCache = 会话仅存储在 Cookie 中
customSession插件:为会话扩展自定义字段
完整的会话管理详情,请参阅 references/sessions.md。
安全检查清单
| 应当做 | 不应做 |
|---|---|
| 使用 32 位以上、高熵的密钥 | 将密钥提交到版本控制中 |
在生产环境中为 baseURL 设置 HTTPS | 禁用 CSRF 检查(disableCSRFCheck) |
为所有前端配置 trustedOrigins | 禁用来源检查 |
| 启用速率限制(生产环境中默认开启) | 在无服务器环境中使用 "memory" 速率限制存储 |
在无服务器环境中配置 backgroundTasks.handler | 跳过电子邮件验证设置 |
对敏感会话数据使用 "jwe" Cookie 缓存 | 如果用于 API 调用,不要以未加密的形式存储 OAuth 令牌 |
设置 revokeSessionsOnPasswordReset: true | 返回具体的错误消息(“未找到用户”) |
完整的安全加固指南请参阅 references/security.md。
常见注意事项
- 模型名称与表名 — 配置使用 ORM 模型名称,而不是数据库表名
- 插件架构 — 添加或更改插件后,重新运行 CLI
- 辅助存储 — 会话默认存储在其中,而非数据库。设置
session.storeSessionInDatabase: true可同时持久化到两处 - Cookie 缓存 — 自定义会话字段不会被缓存,每次都会从数据库重新获取
- 回调 URL — 始终使用包含来源的绝对 URL(而非相对路径)
- Express v5 — 全匹配路由请使用
"/api/auth/*splat",而不是"/api/auth/*" - Next.js RSC — 在身份验证配置中添加
nextCookies()插件,以便在服务器组件中访问会话
故障排除
| 问题 | 解决方法 |
|---|---|
| "Secret not set" | 添加 BETTER_AUTH_SECRET 环境变量 |
| "Invalid Origin" | 将域名添加到 trustedOrigins |
| 未设置 Cookie | 检查 baseURL 是否与域名匹配;在生产环境中启用安全 Cookie |
| OAuth 回调错误 | 确认提供商控制面板中的重定向 URI 完全匹配 |
| 添加插件后出现类型错误 | 重新运行 CLI generate/migrate |
| RSC 中的会话为 null | 添加 nextCookies() 插件 |
| 2FA 重定向不起作用 | 在客户端添加带有 onTwoFactorRedirect 的 twoFactorClient |
参考索引
| 文件 | 阅读时机 |
|---|---|
| setup.md | 设置新项目、配置数据库、路由处理程序时 |
| authentication.md | 实现任何身份验证方式(电子邮件、社交登录、通行密钥、魔法链接等)时 |
| sessions.md | 配置会话过期时间、缓存、无状态模式、辅助存储时 |
| security.md | 为生产环境加固时 — 速率限制、CSRF、Cookie、OAuth 安全 |
| plugins.md | 使用或创建插件、查阅插件目录时 |
| framework-integrations.md | 设置特定框架(Next.js、Nuxt、SvelteKit、Hono、Express 等)时 |
| two-factor.md | 实现 2FA(TOTP、OTP、备用代码、受信任设备)时 |
| organizations.md | 配置多租户组织、团队、邀请、RBAC 时 |
| admin.md | 管理用户、角色、封禁、模拟身份时 |
| hooks-and-middleware.md | 通过前置/后置钩子、数据库钩子、中间件实现自定义逻辑时 |