better-auth-best-practices
提供Better Auth集成指南和最佳实践,指导用户安装、配置环境变量,并查阅官方文档获取最新API和代码示例。
npx skills add better-auth/skills --skill better-auth-best-practicesBefore / After 效果对比
1 组过去集成认证系统时,开发者常面临配置复杂、安全漏洞风险高、难以保持最新API的问题,导致认证流程不稳定且不安全。
遵循Better Auth集成指南和最佳实践,通过正确配置环境变量并查阅官方文档,确保了认证系统的安全性和稳定性,简化了集成过程。
description SKILL.md
better-auth-best-practices
Better Auth Integration Guide
Always consult better-auth.com/docs for code examples and latest API.
Setup Workflow
-
Install:
npm install better-auth -
Set env vars:
BETTER_AUTH_SECRETandBETTER_AUTH_URL -
Create
auth.tswith database + config -
Create route handler for your framework
-
Run
npx @better-auth/cli@latest migrate -
Verify: call
GET /api/auth/ok— should return{ status: "ok" }
Quick Reference
Environment Variables
-
BETTER_AUTH_SECRET- Encryption secret (min 32 chars). Generate:openssl rand -base64 32 -
BETTER_AUTH_URL- Base URL (e.g.,https://example.com)
Only define baseURL/secret in config if env vars are NOT set.
File Location
CLI looks for auth.ts in: ./, ./lib, ./utils, or under ./src. Use --config for custom path.
CLI Commands
-
npx @better-auth/cli@latest migrate- Apply schema (built-in adapter) -
npx @better-auth/cli@latest generate- Generate schema for Prisma/Drizzle -
npx @better-auth/cli mcp --cursor- Add MCP to AI tools
Re-run after adding/changing plugins.
Core Config Options
Option Notes
appName
Optional display name
baseURL
Only if BETTER_AUTH_URL not set
basePath
Default /api/auth. Set / for root.
secret
Only if BETTER_AUTH_SECRET not set
database
Required for most features. See adapters docs.
secondaryStorage
Redis/KV for sessions & rate limits
emailAndPassword
{ enabled: true } to activate
socialProviders
{ google: { clientId, clientSecret }, ... }
plugins
Array of plugins
trustedOrigins
CSRF whitelist
Database
Direct connections: Pass pg.Pool, mysql2 pool, better-sqlite3, or bun:sqlite instance.
ORM adapters: Import from better-auth/adapters/drizzle, better-auth/adapters/prisma, better-auth/adapters/mongodb.
Critical: Better Auth uses adapter model names, NOT underlying table names. If Prisma model is User mapping to table users, use modelName: "user" (Prisma reference), not "users".
Session Management
Storage priority:
-
If
secondaryStoragedefined → sessions go there (not DB) -
Set
session.storeSessionInDatabase: trueto also persist to DB -
No database +
cookieCache→ fully stateless mode
Cookie cache strategies:
-
compact(default) - Base64url + HMAC. Smallest. -
jwt- Standard JWT. Readable but signed. -
jwe- Encrypted. Maximum security.
Key options: session.expiresIn (default 7 days), session.updateAge (refresh interval), session.cookieCache.maxAge, session.cookieCache.version (change to invalidate all sessions).
User & Account Config
User: user.modelName, user.fields (column mapping), user.additionalFields, user.changeEmail.enabled (disabled by default), user.deleteUser.enabled (disabled by default).
Account: account.modelName, account.accountLinking.enabled, account.storeAccountCookie (for stateless OAuth).
Required for registration: email and name fields.
Email Flows
-
emailVerification.sendVerificationEmail- Must be defined for verification to work -
emailVerification.sendOnSignUp/sendOnSignIn- Auto-send triggers -
emailAndPassword.sendResetPassword- Password reset email handler
Security
In advanced:
-
useSecureCookies- Force HTTPS cookies -
disableCSRFCheck- ⚠️ Security risk -
disableOriginCheck- ⚠️ Security risk -
crossSubDomainCookies.enabled- Share cookies across subdomains -
ipAddress.ipAddressHeaders- Custom IP headers for proxies -
database.generateId- Custom ID generation or"serial"/"uuid"/false
Rate limiting: rateLimit.enabled, rateLimit.window, rateLimit.max, rateLimit.storage ("memory" | "database" | "secondary-storage").
Hooks
Endpoint hooks: hooks.before / hooks.after - Array of { matcher, handler }. Use createAuthMiddleware. Access ctx.path, ctx.context.returned (after), ctx.context.session.
Database hooks: databaseHooks.user.create.before/after, same for session, account. Useful for adding default values or post-creation actions.
Hook context (ctx.context): session, secret, authCookies, password.hash()/verify(), adapter, internalAdapter, generateId(), tables, baseURL.
Plugins
Import from dedicated paths for tree-shaking:
import { twoFactor } from "better-auth/plugins/two-factor"
NOT from "better-auth/plugins".
Popular plugins: twoFactor, organization, passkey, magicLink, emailOtp, username, phoneNumber, admin, apiKey, bearer, jwt, multiSession, sso, oauthProvider, oidcProvider, openAPI, genericOAuth.
Client plugins go in createAuthClient({ plugins: [...] }).
Client
Import from: better-auth/client (vanilla), better-auth/react, better-auth/vue, better-auth/svelte, better-auth/solid.
Key methods: signUp.email(), signIn.email(), signIn.social(), signOut(), useSession(), getSession(), revokeSession(), revokeSessions().
Type Safety
Infer types: typeof auth.$Infer.Session, typeof auth.$Infer.Session.user.
For separate client/server projects: createAuthClient<typeof auth>().
Common Gotchas
-
Model vs table name - Config uses ORM model name, not DB table name
-
Plugin schema - Re-run CLI after adding plugins
-
Secondary storage - Sessions go there by default, not DB
-
Cookie cache - Custom session fields NOT cached, always re-fetched
-
Stateless mode - No DB = session in cookie only, logout on cache expiry
-
Change email flow - Sends to current email first, then new email
Resources
Weekly Installs24.3KRepositorybetter-auth/skillsGitHub Stars158First SeenJan 19, 2026Security AuditsGen Agent Trust HubPassSocketPassSnykPassInstalled onopencode16.9Kcodex16.1Kgithub-copilot15.8Kgemini-cli15.7Kcursor14.8Kclaude-code14.4K
forum用户评价 (0)
发表评价
暂无评价
统计数据
用户评分
为此 Skill 评分