关于 better-auth-security-best-practices
面向应用开发者的 Better Auth 安全配置指南,涵盖密钥、速率限制、CSRF、可信来源、会话、Cookie、OAuth 令牌和审计钩子。
主要功能
- 01密钥配置指南
- 02速率限制与存储选项
- 03CSRF 和可信来源控制
- 04会话与 Cookie 安全
- 05OAuth 令牌保护
- 06安全审计钩子
适用场景
- 01为生产环境配置 Better Auth
- 02设置敏感端点的请求限制
- 03保护会话和跨子域 Cookie
- 04为认证操作添加审计日志
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ better-auth/ skills --skill better-auth-security-best-practices安装后在 Claude Code 中输入/better-auth-security-best-practices确认已加载。
详细介绍
密钥管理
配置密钥
import { betterAuth } from "better-auth";
export const auth = betterAuth({
secret: process.env.BETTER_AUTH_SECRET, // or via `BETTER_AUTH_SECRET` env
});
Better Auth 按以下顺序查找密钥:
- 配置中的
options.secret BETTER_AUTH_SECRET环境变量AUTH_SECRET环境变量
密钥要求
- 在生产环境中拒绝默认或占位密钥
- 如果密钥长度少于 32 个字符或熵低于 120 位,则发出警告
- 生成密钥:
openssl rand -base64 32 - 切勿将密钥提交到版本控制系统
速率限制
默认在生产环境中启用,并应用于所有端点。插件可以覆盖特定端点的设置。
默认配置
import { betterAuth } from "better-auth";
export const auth = betterAuth({
rateLimit: {
enabled: true, // Default: true in production
window: 10, // Time window in seconds (default: 10)
max: 100, // Max requests per window (default: 100)
},
});
存储选项
可选项:"memory"(重启后重置,请勿用于无服务器环境)、"database"(持久化)、"secondary-storage"(Redis;有可用存储时默认使用)。
rateLimit: {
storage: "database",
}
自定义存储
自行实现速率限制存储:
rateLimit: {
customStorage: {
get: async (key) => {
// Return { count: number, expiresAt: number } or null
},
set: async (key, data) => {
// Store the rate limit data
},
},
}
特定端点规则
敏感端点默认每 10 秒允许 3 次请求(/sign-in、/sign-up、/change-password、/change-email)。覆盖设置:
rateLimit: {
customRules: {
"/api/auth/sign-in/email": {
window: 60, // 1 minute window
max: 5, // 5 attempts
},
"/api/auth/some-safe-endpoint": false, // Disable rate limiting
},
}
CSRF 防护
多层防护:源站标头验证、Fetch Metadata 检查和首次登录防护。
配置
import { betterAuth } from "better-auth";
export const auth = betterAuth({
advanced: {
disableCSRFCheck: false, // Default: false (keep enabled)
},
});
仅在测试或使用其他 CSRF 防护机制时禁用。
可信来源
配置可信来源
import { betterAuth } from "better-auth";
export const auth = betterAuth({
baseURL: "https://api.example.com",
trustedOrigins: [
"https://app.example.com",
"https://admin.example.com",
],
});
baseURL 的源站会自动设为可信来源。也可以通过环境变量配置:BETTER_AUTH_TRUSTED_ORIGINS=https://app.example.com,https://admin.example.com
通配符模式
trustedOrigins: [
"*.example.com", // Matches any subdomain
"https://*.example.com", // Protocol-specific wildcard
"exp://192.168.*.*:*/*", // Custom schemes (e.g., Expo)
]
动态可信来源
根据请求计算可信来源:
trustedOrigins: async (request) => {
// Validate against database, header, etc.
const tenant = getTenantFromRequest(request);
return [`https://${tenant}.myapp.com`];
}
会针对可信来源验证 callbackURL、redirectTo、errorCallbackURL、newUserCallbackURL 和 origin。无效 URL 会收到 403 响应。
会话安全
会话过期
import { betterAuth } from "better-auth";
export const auth = betterAuth({
session: {
expiresIn: 60 * 60 * 24 * 7, // 7 days (default)
updateAge: 60 * 60 * 24, // Refresh session every 24 hours (default)
},
});
会话缓存策略
将会话数据缓存在 Cookie 中,以减少数据库查询:
session: {
cookieCache: {
enabled: true,
maxAge: 60 * 5, // 5 minutes
strategy: "compact", // Options: "compact", "jwt", "jwe"
},
}
策略:"compact"(Base64url + HMAC,体积最小)、"jwt"(HS256,标准方式)、"jwe"(加密;会话包含敏感数据时使用)。
Cookie 安全
默认值:secure: true(HTTPS/生产环境)、sameSite: "lax"、httpOnly: true、path: "/",前缀为 __Secure-。
自定义 Cookie 配置
import { betterAuth } from "better-auth";
export const auth = betterAuth({
advanced: {
useSecureCookies: true, // Force secure cookies
cookiePrefix: "myapp", // Custom prefix (default: "better-auth")
defaultCookieAttributes: {
sameSite: "strict", // Stricter CSRF protection
path: "/auth", // Limit cookie scope
},
},
});
跨子域 Cookie
advanced: {
crossSubDomainCookies: {
enabled: true,
domain: ".example.com", // Note the leading dot
additionalCookies: ["session_token", "session_data"],
},
}
仅在需要共享身份验证且信任所有子域时启用。
OAuth/社交服务提供商安全
所有 OAuth 流程都会自动使用 PKCE。State 令牌是 32 个字符的随机字符串,10 分钟后过期。
State 参数存储
import { betterAuth } from "better-auth";
export const auth = betterAuth({
account: {
storeStateStrategy: "cookie", // Options: "cookie" (default), "database"
},
});
加密 OAuth 令牌
account: {
encryptOAuthTokens: true, // Uses AES-256-GCM
}
如果要存储 OAuth 令牌,以代表用户访问 API,请启用此选项。仅当无法维持 Cookie 的移动应用需要时,才使用 skipStateCookieCheck: true。
基于 IP 的安全防护
IP 地址配置
import { betterAuth } from "better-auth";
export const auth = betterAuth({
advanced: {
ipAddress: {
ipAddressHeaders: ["x-forwarded-for", "x-real-ip"], // Headers to check
disableIpTracking: false, // Keep enabled for rate limiting
},
},
});
设置 ipv6Subnet(128、64、48、32;默认为 64)以对 IPv6 地址分组。仅当处于可信反向代理之后时,才启用 trustedProxyHeaders: true。
用于安全审计的数据库钩子
import { betterAuth } from "better-auth";
export const auth = betterAuth({
databaseHooks: {
session: {
create: {
after: async ({ data, ctx }) => {
await auditLog("session.created", {
userId: data.userId,
ip: ctx?.request?.headers.get("x-forwarded-for"),
userAgent: ctx?.request?.headers.get("user-agent"),
});
},
},
delete: {
before: async ({ data }) => {
await auditLog("session.revoked", { sessionId: data.id });
},
},
},
user: {
update: {
after: async ({ data, oldData }) => {
if (oldData?.email !== data.email) {
await auditLog("user.email_changed", {
userId: data.id,
oldEmail: oldData?.email,
newEmail: data.email,
});
}
},
},
},
account: {
create: {
after: async ({ data }) => {
await auditLog("account.linked", {
userId: data.userId,
provider: data.providerId,
});
},
},
},
},
});
在 before 钩子中返回 false,即可阻止操作。
后台任务
import { betterAuth } from "better-auth";
export const auth = betterAuth({
advanced: {
backgroundTasks: {
handler: (promise) => {
// Platform-specific handler
// Vercel: waitUntil(promise)
// Cloudflare: ctx.waitUntil(promise)
waitUntil(promise);
},
},
},
});
确保发送电子邮件等操作不会影响响应时间。
防止账号枚举
内置措施:使用一致的响应消息、对无效请求执行虚拟操作、在后台发送电子邮件。返回通用错误消息(“凭据无效”),而非具体错误消息(“未找到用户”)。
完整安全配置示例
import { betterAuth } from "better-auth";
export const auth = betterAuth({
secret: process.env.BETTER_AUTH_SECRET,
baseURL: "https://api.example.com",
trustedOrigins: [
"https://app.example.com",
"https://*.preview.example.com",
],
// Rate limiting
rateLimit: {
enabled: true,
storage: "secondary-storage",
customRules: {
"/api/auth/sign-in/email": { window: 60, max: 5 },
"/api/auth/sign-up/email": { window: 60, max: 3 },
},
},
// Session security
session: {
expiresIn: 60 * 60 * 24 * 7, // 7 days
updateAge: 60 * 60 * 24, // 24 hours
freshAge: 60 * 60, // 1 hour for sensitive actions
cookieCache: {
enabled: true,
maxAge: 300,
strategy: "jwe", // Encrypted session data
},
},
// OAuth security
account: {
encryptOAuthTokens: true,
storeStateStrategy: "cookie",
},
// Advanced settings
advanced: {
useSecureCookies: true,
cookiePrefix: "myapp",
defaultCookieAttributes: {
sameSite: "lax",
},
ipAddress: {
ipAddressHeaders: ["x-forwarded-for"],
ipv6Subnet: 64,
},
backgroundTasks: {
handler: (promise) => waitUntil(promise),
},
},
// Security auditing
databaseHooks: {
session: {
create: {
after: async ({ data, ctx }) => {
console.log(`New session for user ${data.userId}`);
},
},
},
user: {
update: {
after: async ({ data, oldData }) => {
if (oldData?.email !== data.email) {
console.log(`Email changed for user ${data.id}`);
}
},
},
},
},
});
安全检查清单
部署到生产环境之前:
- 密钥:使用强度高且唯一的密钥(32 个以上字符,具有高熵)
- HTTPS:确保
baseURL使用 HTTPS - 可信来源:配置所有有效来源(前端、移动应用)
- 速率限制:保持启用,并设置适当的限制
- CSRF 保护:保持启用(
disableCSRFCheck: false) - 安全 Cookie:使用 HTTPS 时自动启用
- OAuth 令牌:如果要存储令牌,请考虑设置
encryptOAuthTokens: true - 后台任务:为无服务器平台进行配置
- 审计日志:通过
databaseHooks或hooks实现 - IP 跟踪:如果位于代理之后,请配置请求头