mcpField
B
better-auth

better-auth

github.com/jackspace安全1647 次安装12 周前更新
代码仓库

关于 better-auth

用于 better-auth 的技能;better-auth 是与框架无关的 TypeScript 身份验证与授权库。内容涵盖配置、数据库集成、进阶认证功能和迁移方法。

主要功能

  1. 01为 TypeScript 应用配置身份验证
  2. 02集成 D1 和其他数据库
  3. 03添加双重验证和通行密钥
  4. 04管理组织和多租户
  5. 05配置社交登录和速率限制
  6. 06参考迁移指南

适用场景

  1. 01为使用 D1 的 Cloudflare Workers 应用配置认证
  2. 02为 SaaS 应用添加组织支持
  3. 03将应用从 Clerk 或 Auth.js 迁移

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jackspace/claudeskillz --skill better-auth

安装后在 Claude Code 中输入/better-auth确认已加载。

附带文件README.mdSKILL.json

详细介绍

better-auth 技能

概述

better-auth 是一个全面、与框架无关的 TypeScript 身份验证与授权库。它提供完整的身份验证解决方案,并原生支持 Cloudflare D1,因此是 Clerk 或 Auth.js 的优秀可自托管替代方案。

在以下情况下使用此技能:

  • 为 Cloudflare Workers + D1 应用构建身份验证
  • 需要可自托管、独立于供应商的身份验证解决方案
  • 从 Clerk 迁移(避免供应商锁定)
  • 从 Auth.js 升级(需要更多功能)
  • 使用组织/团队实现多租户 SaaS
  • 需要高级功能:双重身份验证、通行密钥、RBAC、社交身份验证

软件包:[email protected](最新验证日期:2025-10-31)


安装

核心软件包
npm install better-auth
# or
pnpm add better-auth
# or
yarn add better-auth
数据库适配器

用于 Cloudflare D1(Workers):

npm install @cloudflare/workers-types

用于 PostgreSQL:

npm install pg drizzle-orm

用于 MySQL/SQLite:内置适配器,无需额外软件包。

社交身份验证提供商(可选)
npm install @better-auth/google
npm install @better-auth/github
npm install @better-auth/microsoft

快速入门模式

模式 1:Cloudflare Workers + D1

适用情况:使用 D1 数据库在 Cloudflare Workers 上构建 API

文件:src/worker.ts

import { betterAuth } from 'better-auth'
import { d1Adapter } from 'better-auth/adapters/d1'
import { Hono } from 'hono'

type Env = {
  DB: D1Database
  BETTER_AUTH_SECRET: string
  GOOGLE_CLIENT_ID: string
  GOOGLE_CLIENT_SECRET: string
}

const app = new Hono<{ Bindings: Env }>()

// Auth routes handler
app.all('/api/auth/*', async (c) => {
  const auth = betterAuth({
    database: d1Adapter(c.env.DB),
    secret: c.env.BETTER_AUTH_SECRET,

    // Basic auth methods
    emailAndPassword: {
      enabled: true,
      requireEmailVerification: true
    },

    // Social providers
    socialProviders: {
      google: {
        clientId: c.env.GOOGLE_CLIENT_ID,
        clientSecret: c.env.GOOGLE_CLIENT_SECRET
      }
    }
  })

  return auth.handler(c.req.raw)
})

export default app

wrangler.toml:

name = "my-app"
main = "src/worker.ts"
compatibility_date = "2024-01-01"

[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "your-database-id"

[vars]
# Public vars here

# Secrets (use: wrangler secret put BETTER_AUTH_SECRET)
# - BETTER_AUTH_SECRET
# - GOOGLE_CLIENT_ID
# - GOOGLE_CLIENT_SECRET

设置 D1 数据库:

# Create database
wrangler d1 create my-app-db

# Generate migration SQL from better-auth
npx better-auth migrate --database d1

# Apply migration
wrangler d1 execute my-app-db --remote --file migrations/0001_initial.sql

模式 2:Next.js API 路由

适用情况:使用 PostgreSQL 或 D1 构建传统 Next.js 应用

文件:src/lib/auth.ts

import { betterAuth } from 'better-auth'
import { Pool } from 'pg'

export const auth = betterAuth({
  database: new Pool({
    connectionString: process.env.DATABASE_URL
  }),

  secret: process.env.BETTER_AUTH_SECRET!,

  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
    sendVerificationEmail: async ({ user, url }) => {
      // Send email with verification link
      await sendEmail({
        to: user.email,
        subject: 'Verify your email',
        html: `Click <a href="${url}">here</a> to verify`
      })
    }
  },

  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!
    },
    github: {
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!
    }
  },

  // Advanced features via plugins
  plugins: [
    twoFactor(),
    organization(),
    rateLimit()
  ]
})

文件:src/app/api/auth/[...all]/route.ts

import { auth } from '@/lib/auth'

export const GET = auth.handler
export const POST = auth.handler

模式 3:React 客户端集成

适用情况:需要客户端身份验证状态和操作

文件:src/lib/auth-client.ts

import { createAuthClient } from 'better-auth/client'

export const authClient = createAuthClient({
  baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'
})

文件:src/components/LoginForm.tsx

'use client'

import { authClient } from '@/lib/auth-client'
import { useState } from 'react'

export function LoginForm() {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()

    const { data, error } = await authClient.signIn.email({
      email,
      password
    })

    if (error) {
      console.error('Login failed:', error)
      return
    }

    // Redirect or update UI
    window.location.href = '/dashboard'
  }

  const handleGoogleSignIn = async () => {
    await authClient.signIn.social({
      provider: 'google',
      callbackURL: '/dashboard'
    })
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password"
      />
      <button type="submit">Sign In</button>
      <button type="button" onClick={handleGoogleSignIn}>
        Sign in with Google
      </button>
    </form>
  )
}

使用 React Hook(如果你有会话端点):

'use client'

import { useSession } from 'better-auth/client'

export function UserProfile() {
  const { data: session, isPending } = useSession()

  if (isPending) return <div>Loading...</div>
  if (!session) return <div>Not authenticated</div>

  return (
    <div>
      <p>Welcome, {session.user.email}</p>
      <button onClick={() => authClient.signOut()}>
        Sign Out
      </button>
    </div>
  )
}

模式 4:受保护的 API 路由(中间件)

适用情况:需要在 API 路由中验证会话

Cloudflare Workers:

import { betterAuth } from 'better-auth'
import { d1Adapter } from 'better-auth/adapters/d1'

app.get('/api/protected', async (c) => {
  const auth = betterAuth({
    database: d1Adapter(c.env.DB),
    secret: c.env.BETTER_AUTH_SECRET
  })

  const session = await auth.getSession(c.req.raw)

  if (!session) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  return c.json({
    message: 'Protected data',
    user: session.user
  })
})

Next.js 中间件:

// middleware.ts
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/lib/auth'

export async function middleware(request: NextRequest) {
  const session = await auth.getSession(request)

  if (!session && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/dashboard/:path*']
}

高级功能

双重身份验证(2FA)
import { betterAuth } from 'better-auth'
import { twoFactor } from 'better-auth/plugins'

export const auth = betterAuth({
  database: /* ... */,
  plugins: [
    twoFactor({
      methods: ['totp', 'sms'], // Time-based or SMS
      issuer: 'MyApp'
    })
  ]
})

客户端:

// Enable 2FA for user
const { data, error } = await authClient.twoFactor.enable({
  method: 'totp'
})

// Verify code
await authClient.twoFactor.verify({
  code: '123456'
})

组织与团队
import { betterAuth } from 'better-auth'
import { organization } from 'better-auth/plugins'

export const auth = betterAuth({
  database: /* ... */,
  plugins: [
    organization({
      roles: ['owner', 'admin', 'member'],
      permissions: {
        admin: ['read', 'write', 'delete'],
        member: ['read']
      }
    })
  ]
})

客户端:

// Create organization
await authClient.organization.create({
  name: 'Acme Corp',
  slug: 'acme'
})

// Invite member
await authClient.organization.inviteMember({
  organizationId: 'org_123',
  email: '[email protected]',
  role: 'member'
})

// Check permissions
const canDelete = await authClient.organization.hasPermission({
  organizationId: 'org_123',
  permission: 'delete'
})

多租户 SaaS
import { betterAuth } from 'better-auth'
import { multiTenant } from 'better-auth/plugins'

export const auth = betterAuth({
  database: /* ... */,
  plugins: [
    multiTenant({
      tenantIdHeader: 'x-tenant-id',
      isolateData: true // Ensure tenant data isolation
    })
  ]
})

速率限制
import { betterAuth } from 'better-auth'
import { rateLimit } from 'better-auth/plugins'

export const auth = betterAuth({
  database: /* ... */,
  plugins: [
    rateLimit({
      window: 60, // 60 seconds
      max: 5, // 5 requests per window
      storage: 'database' // or 'memory'
    })
  ]
})

用于 Cloudflare:使用 KV 实现分布式速率限制:

import { rateLimit } from 'better-auth/plugins'

plugins: [
  rateLimit({
    window: 60,
    max: 5,
    storage: {
      get: async (key) => {
        return await c.env.RATE_LIMIT_KV.get(key)
      },
      set: async (key, value, ttl) => {
        await c.env.RATE_LIMIT_KV.put(key, value, { expirationTtl: ttl })
      }
    }
  })
]

数据库设置

D1 架构迁移
# Generate migration
npx better-auth migrate --database d1

# This creates: migrations/0001_initial.sql

应用迁移:

# Local
wrangler d1 execute my-app-db --local --file migrations/0001_initial.sql

# Production
wrangler d1 execute my-app-db --remote --file migrations/0001_initial.sql

手动架构(如有需要):

-- better-auth core tables
CREATE TABLE users (
  id TEXT PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  emailVerified INTEGER DEFAULT 0,
  name TEXT,
  image TEXT,
  createdAt INTEGER NOT NULL,
  updatedAt INTEGER NOT NULL
);

CREATE TABLE sessions (
  id TEXT PRIMARY KEY,
  userId TEXT NOT NULL,
  expiresAt INTEGER NOT NULL,
  ipAddress TEXT,
  userAgent TEXT,
  FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE
);

CREATE TABLE accounts (
  id TEXT PRIMARY KEY,
  userId TEXT NOT NULL,
  provider TEXT NOT NULL,
  providerAccountId TEXT NOT NULL,
  accessToken TEXT,
  refreshToken TEXT,
  expiresAt INTEGER,
  FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE
);

CREATE TABLE verification_tokens (
  identifier TEXT NOT NULL,
  token TEXT NOT NULL,
  expires INTEGER NOT NULL,
  PRIMARY KEY (identifier, token)
);

-- Additional tables for plugins (organizations, 2FA, etc.)

使用 Drizzle 的 PostgreSQL

文件:src/db/schema.ts

import { pgTable, text, timestamp, boolean } from 'drizzle-orm/pg-core'

export const users = pgTable('users', {
  id: text('id').primaryKey(),
  email: text('email').unique().notNull(),
  emailVerified: boolean('email_verified').default(false),
  name: text('name'),
  image: text('image'),
  createdAt: timestamp('created_at').notNull().defaultNow(),
  updatedAt: timestamp('updated_at').notNull().defaultNow()
})

// ... other tables

设置:

import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import { betterAuth } from 'better-auth'

const client = postgres(process.env.DATABASE_URL!)
const db = drizzle(client)

export const auth = betterAuth({
  database: db,
  // ...
})

社交身份验证提供商设置

Google OAuth
  1. 创建 OAuth 凭据:https://console.cloud.google.com/apis/credentials
  2. 授权重定向 URI:https://yourdomain.com/api/auth/callback/google
  3. 环境变量:
    GOOGLE_CLIENT_ID=your-client-id
    GOOGLE_CLIENT_SECRET=your-client-secret
    

配置:

socialProviders: {
  google: {
    clientId: process.env.GOOGLE_CLIENT_ID!,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    scope: ['email', 'profile'] // Optional
  }
}

GitHub OAuth
  1. 创建 OAuth 应用:https://github.com/settings/developers
  2. 授权回调 URL:https://yourdomain.com/api/auth/callback/github
  3. 环境变量:
    GITHUB_CLIENT_ID=your-client-id
    GITHUB_CLIENT_SECRET=your-client-secret
    

配置:

socialProviders: {
  github: {
    clientId: process.env.GITHUB_CLIENT_ID!,
    clientSecret: process.env.GITHUB_CLIENT_SECRET!
  }
}

Microsoft OAuth
npm install @better-auth/microsoft
  1. Azure 门户:https://portal.azure.com → 应用注册
  2. 重定向 URI:https://yourdomain.com/api/auth/callback/microsoft
  3. 环境变量:
    MICROSOFT_CLIENT_ID=your-client-id
    MICROSOFT_CLIENT_SECRET=your-client-secret
    MICROSOFT_TENANT_ID=common  # or your tenant ID
    

配置:

import { microsoft } from '@better-auth/microsoft'

socialProviders: {
  microsoft: microsoft({
    clientId: process.env.MICROSOFT_CLIENT_ID!,
    clientSecret: process.env.MICROSOFT_CLIENT_SECRET!,
    tenantId: process.env.MICROSOFT_TENANT_ID!
  })
}

迁移指南

从 Clerk 迁移

主要区别:

  • Clerk:第三方服务 → better-auth:可自托管
  • Clerk:专有软件 → better-auth:开源
  • Clerk:按月收费 → better-auth:免费

迁移步骤:

  1. 从 Clerk 导出用户数据(CSV 或 API)
  2. 导入 better-auth 数据库:
    // migration script
    const clerkUsers = await fetchClerkUsers()
    
    for (const clerkUser of clerkUsers) {
      await db.insert(users).values({
        id: clerkUser.id,
        email: clerkUser.email,
        emailVerified: clerkUser.email_verified,
        name: clerkUser.first_name + ' ' + clerkUser.last_name,
        image: clerkUser.profile_image_url
      })
    }
    
  3. 将 Clerk SDK 替换为 better-auth 客户端:
    // Before (Clerk)
    import { useUser } from '@clerk/nextjs'
    const { user } = useUser()
    
    // After (better-auth)
    import { useSession } from 'better-auth/client'
    const { data: session } = useSession()
    const user = session?.user
    
  4. 更新中间件以验证会话
  5. 配置社交身份验证提供商(使用相同的 OAuth 应用,但配置不同)

来自 Auth.js(NextAuth)

主要区别:

  • Auth.js:功能有限 → better-auth:功能全面(2FA、组织等)
  • Auth.js:依赖大量回调 → better-auth:基于插件
  • Auth.js:会话处理方式各异 → better-auth:保持一致

迁移步骤:

  1. 数据库架构:Auth.js 和 better-auth 使用相似的架构,但列名不同
    -- Map Auth.js to better-auth
    ALTER TABLE users RENAME COLUMN emailVerified TO email_verified;
    -- etc.
    
  2. 替换配置:
    // Before (Auth.js)
    import NextAuth from 'next-auth'
    import GoogleProvider from 'next-auth/providers/google'
    
    export default NextAuth({
      providers: [GoogleProvider({ /* ... */ })]
    })
    
    // After (better-auth)
    import { betterAuth } from 'better-auth'
    
    export const auth = betterAuth({
      socialProviders: {
        google: { /* ... */ }
      }
    })
    
  3. 更新客户端钩子:
    // Before
    import { useSession } from 'next-auth/react'
    
    // After
    import { useSession } from 'better-auth/client'
    

已知问题与解决方案

问题 1:D1 的最终一致性

问题:在 D1 中,写入后立即读取会话可能返回过期数据。

症状:用户登录后,下一次请求中 getSession() 返回 null。

解决方案:使用 Cloudflare KV 存储会话(强一致性):

import { betterAuth } from 'better-auth'

export const auth = betterAuth({
  database: d1Adapter(env.DB), // Users, accounts
  session: {
    storage: {
      get: async (sessionId) => {
        const session = await env.SESSIONS_KV.get(sessionId)
        return session ? JSON.parse(session) : null
      },
      set: async (sessionId, session, ttl) => {
        await env.SESSIONS_KV.put(
          sessionId,
          JSON.stringify(session),
          { expirationTtl: ttl }
        )
      },
      delete: async (sessionId) => {
        await env.SESSIONS_KV.delete(sessionId)
      }
    }
  }
})

来源:https://github.com/better-auth/better-auth/issues/147


问题 2:SPA 应用的 CORS

问题:认证 API 与前端位于不同源时会出现 CORS 错误。

症状:浏览器控制台中出现 Access-Control-Allow-Origin 错误。

解决方案:在 Worker 中配置 CORS 标头:

import { Hono } from 'hono'
import { cors } from 'hono/cors'

const app = new Hono<{ Bindings: Env }>()

app.use('/api/auth/*', cors({
  origin: ['https://yourdomain.com', 'http://localhost:3000'],
  credentials: true, // Allow cookies
  allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']
}))

app.all('/api/auth/*', async (c) => {
  const auth = betterAuth({ /* ... */ })
  return auth.handler(c.req.raw)
})

来源:https://better-auth.com/docs/guides/cors


问题 3:Worker 中的会话序列化

问题:无法在 Cloudflare Workers 中序列化复杂的会话对象。

症状:出现 DataCloneError,或会话数据缺失。

解决方案:保持会话数据精简且可通过 JSON 序列化:

export const auth = betterAuth({
  database: d1Adapter(env.DB),
  session: {
    // Only include serializable fields
    fields: {
      userId: true,
      email: true,
      role: true
      // Don't include: functions, Dates, complex objects
    }
  }
})

问题 4:OAuth 重定向 URI 不匹配

问题:社交登录失败,并出现“redirect_uri_mismatch”错误。

症状:用户授权后,Google/GitHub OAuth 返回错误。

解决方案:确保 OAuth 提供商设置中的 URI 完全匹配:

Provider setting: https://yourdomain.com/api/auth/callback/google
better-auth URL:  https://yourdomain.com/api/auth/callback/google

❌ Wrong: http vs https, trailing slash, subdomain mismatch
✅ Right: Exact character-for-character match

检查 better-auth 回调 URL:

// It's always: {baseURL}/api/auth/callback/{provider}
const callbackURL = `${process.env.NEXT_PUBLIC_API_URL}/api/auth/callback/google`
console.log('Configure this URL in Google Console:', callbackURL)

问题 5:验证邮件未发送

问题:验证邮件链接始终无法送达。

症状:用户注册后未收到邮件。

解决方案:实现 sendVerificationEmail 处理程序:

export const auth = betterAuth({
  database: /* ... */,
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
    sendVerificationEmail: async ({ user, url, token }) => {
      // Use your email service (SendGrid, Resend, etc.)
      await sendEmail({
        to: user.email,
        subject: 'Verify your email',
        html: `
          <p>Click the link below to verify your email:</p>
          <a href="${url}">Verify Email</a>
          <p>Or use this code: ${token}</p>
        `
      })
    }
  }
})

针对 Cloudflare:使用 Cloudflare Email Routing 或外部服务(Resend、SendGrid)。


问题 6:JWT 令牌过期

问题:会话过期过快或永不过期。

症状:用户意外退出登录,或退出登录后会话仍然存在。

解决方案:配置会话过期时间:

export const auth = betterAuth({
  database: /* ... */,
  session: {
    expiresIn: 60 * 60 * 24 * 7, // 7 days (in seconds)
    updateAge: 60 * 60 * 24 // Update session every 24 hours
  }
})

问题 7:密码哈希性能

问题:在 Cloudflare Workers 上注册/登录速度较慢。

症状:认证请求耗时超过 1 秒。

解决方案:better-auth 默认使用 bcrypt,较为消耗 CPU。对于 Workers,请确保正确地进行异步处理:

// better-auth handles this internally, but if custom:
import bcrypt from 'bcryptjs'

// Use async version (not sync)
const hash = await bcrypt.hash(password, 10) // ✅
const isValid = await bcrypt.compare(password, hash) // ✅

// Don't use:
const hash = bcrypt.hashSync(password, 10) // ❌ (blocks)

替代方案:使用 better-auth 内置的哈希功能(已优化)。


问题 8:社交提供商的权限范围问题

问题:社交登录成功,但缺少用户数据(姓名、头像)。

症状:通过 Google/GitHub 登录后,session.user.name 为 null。

解决方案:请求额外的权限范围:

socialProviders: {
  google: {
    clientId: process.env.GOOGLE_CLIENT_ID!,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    scope: ['openid', 'email', 'profile'] // Include 'profile' for name/image
  },
  github: {
    clientId: process.env.GITHUB_CLIENT_ID!,
    clientSecret: process.env.GITHUB_CLIENT_SECRET!,
    scope: ['user:email', 'read:user'] // 'read:user' for full profile
  }
}

问题 9:多租户数据泄露

问题:用户可以看到其他租户的数据。

症状:组织 A 中的用户能看到组织 B 的数据。

解决方案:始终按租户 ID 筛选查询:

import { multiTenant } from 'better-auth/plugins'

export const auth = betterAuth({
  database: /* ... */,
  plugins: [
    multiTenant({
      tenantIdHeader: 'x-tenant-id',
      isolateData: true // Enforces tenant isolation
    })
  ]
})

// In API routes
app.get('/api/data', async (c) => {
  const session = await auth.getSession(c.req.raw)
  const tenantId = c.req.header('x-tenant-id')

  // ALWAYS filter by tenant
  const data = await db.query.items.findMany({
    where: eq(items.tenantId, tenantId)
  })

  return c.json(data)
})

问题 10:速率限制误报

问题:正常用户被速率限制拦截。

症状:正常使用时出现“请求过多”错误。

解决方案:使用 IP 和用户 ID 作为速率限制键:

import { rateLimit } from 'better-auth/plugins'

plugins: [
  rateLimit({
    window: 60,
    max: 10,
    keyGenerator: (req) => {
      // Combine IP and user ID (if authenticated)
      const ip = req.headers.get('cf-connecting-ip') || 'unknown'
      const userId = req.session?.userId || 'anonymous'
      return `${ip}:${userId}`
    }
  })
]

对比:better-auth 与替代方案

特性better-authClerkAuth.js
托管方式可自托管第三方可自托管
费用免费(OSS)$25/月起免费(OSS)
Cloudflare D1✅ 一等支持❌ 不支持✅ 适配器
社交认证✅ 10+ 个提供商✅ 多种✅ 多种
双重身份验证/通行密钥✅ 插件✅ 内置⚠️ 有限支持
组织✅ 插件✅ 内置❌ 不支持
多租户✅ 插件✅ 支持❌ 不支持
RBAC✅ 插件✅ 支持⚠️ 自定义
魔法链接✅ 内置✅ 支持✅ 支持
电子邮件/密码✅ 内置✅ 支持✅ 支持
会话管理✅ JWT + DB✅ JWT✅ JWT + DB
TypeScript✅ 一等支持✅ 支持✅ 支持
框架支持✅ 不限框架⚠️ 侧重 React✅ 不限框架
供应商锁定✅ 无❌ 高✅ 无
自定义能力✅ 完全掌控⚠️ 有限✅ 完全掌控
可用于生产环境✅ 可以✅ 可以✅ 可以

建议:

  • 适合使用 better-auth 的情况:需要可自托管、Cloudflare D1、完全掌控,或希望避免供应商锁定
  • 适合使用 Clerk 的情况:需要托管服务、不介意费用,且希望尽快完成设置
  • 适合使用 Auth.js 的情况:已经在使用 Next.js、需求基础,且熟悉它

最佳实践

安全
  1. 生产环境始终使用 HTTPS(无一例外)
  2. 定期轮换密钥:
    # Generate new secret
    openssl rand -base64 32
    
    # Update in Wrangler
    wrangler secret put BETTER_AUTH_SECRET
    
  3. 验证注册时的电子邮件域名:
    emailAndPassword: {
      enabled: true,
      validate: async (email) => {
        const blockedDomains = ['tempmail.com', 'guerrillamail.com']
        const domain = email.split('@')[1]
        if (blockedDomains.includes(domain)) {
          throw new Error('Email domain not allowed')
        }
      }
    }
    
  4. 启用 CSRF 防护(better-auth 默认启用)
  5. 为认证端点启用速率限制
  6. 记录认证事件以进行安全监控:
    onSuccess: async (user, action) => {
      await logAuthEvent({
        userId: user.id,
        action, // 'sign-in', 'sign-up', 'password-change'
        timestamp: new Date(),
        ipAddress: req.headers.get('cf-connecting-ip')
      })
    }
    

性能
  1. 缓存会话查询结果(Workers 中使用 KV):

    const session = await env.SESSIONS_KV.get(sessionId)
    if (session) return JSON.parse(session)
    
    // Fallback to DB if not in cache
    const dbSession = await db.query.sessions.findFirst(/* ... */)
    await env.SESSIONS_KV.put(sessionId, JSON.stringify(dbSession))
    
  2. 为频繁查询的字段创建索引:

    CREATE INDEX idx_sessions_user_id ON sessions(userId);
    CREATE INDEX idx_accounts_provider ON accounts(provider, providerAccountId);
    
  3. 尽量减少会话数据(仅保留必要字段)

  4. 为认证端点使用 CDN(缓存公开路由):

    // Cache GET /api/auth/session for 5 minutes
    c.header('Cache-Control', 'public, max-age=300')
    

开发工作流
  1. 使用特定于环境的配置:

    const isDev = process.env.NODE_ENV === 'development'
    
    export const auth = betterAuth({
      database: /* ... */,
      baseURL: isDev
        ? 'http://localhost:3000'
        : 'https://yourdomain.com',
      session: {
        expiresIn: isDev
          ? 60 * 60 * 24 * 365 // 1 year for dev
          : 60 * 60 * 24 * 7    // 7 days for prod
      }
    })
    
  2. 使用 ngrok 在本地测试社交认证:

    ngrok http 3000
    # Use ngrok URL as redirect URI in OAuth provider
    
  3. 为开发环境准备测试用户:

    // seed.ts
    const testUsers = [
      { email: '[email protected]', password: 'password123', role: 'admin' },
      { email: '[email protected]', password: 'password123', role: 'user' }
    ]
    
    for (const user of testUsers) {
      await authClient.signUp.email(user)
    }
    

附带资源

此技能包含以下参考实现:

  1. scripts/setup-d1.sh - 为 Cloudflare Workers 自动设置 D1 数据库
  2. references/cloudflare-worker-example.ts - 包含认证和受保护路由的完整 Worker
  3. references/nextjs-api-route.ts - Next.js API 路由模式
  4. references/react-client-hooks.tsx - 带认证钩子的 React 组件
  5. references/drizzle-schema.ts - better-auth 表的 Drizzle ORM 架构
  6. assets/auth-flow-diagram.md - OAuth、电子邮件验证的可视化流程图

需要时使用 Read 工具访问这些文件。


Token 效率

不使用此技能:约 15,000 个 token(设置时反复试错、调试 CORS、D1 适配器和 OAuth 流程) 使用此技能:约 4,500 个 token(直接根据模式实现) 节省:约 70%(10,500 个 token)

可避免的错误:记录了 10 个常见问题及其解决方案


其他资源


版本兼容性

已测试版本:

破坏性变更:升级时请查看变更日志:https://github.com/better-auth/better-auth/releases


最后验证时间:2025-10-31 | 技能版本:1.0.0

评论

支持 Markdown