202509
web

基于插件的 Auth.js 到 Better Auth 工程化迁移

工程化插件式从 Auth.js 迁移到 Better Auth,保留 OAuth/credential flows,实现零停机 session bridging 和自定义 provider hooks。

在现代 Web 应用开发中,认证系统是核心基础设施之一。随着 Better Auth 的兴起,许多开发者开始考虑从传统的 Auth.js(前身为 NextAuth.js)迁移到这个更全面、框架无关的 TypeScript 认证框架。Better Auth 通过其插件生态系统,提供开箱即用的高级功能,如 2FA、多租户支持和自动数据库管理,同时保持对 OAuth 和凭证认证流的兼容性。本文聚焦于插件式迁移策略,强调零停机会话桥接和自定义提供者钩子的工程化实现,帮助开发者在生产环境中平滑过渡,避免用户中断。

为什么选择插件式迁移?

Auth.js 虽然社区庞大,但其配置复杂、文档有时晦涩,且缺乏内置的速率限制和高级安全特性。相比之下,Better Auth 采用模块化设计,支持插件扩展,能无缝集成 Drizzle、Prisma 等 ORM,并提供类型安全的 API。根据官方文档,Better Auth 的插件系统允许开发者渐进式替换组件,而非大刀阔斧的重构。这使得迁移过程可控,尤其适合中大型应用,其中认证流涉及 OAuth(如 Google、GitHub)和凭证(email/password)登录。

插件式迁移的核心观点是:不一次性替换整个系统,而是通过自定义钩子桥接旧新会话,确保用户在迁移期间无需重新登录。证据显示,这种方法在实际项目中可将停机时间降至零。例如,在一个支持多提供者的 SaaS 应用中,我们使用 Better Auth 的 organization 插件保留了 Auth.js 的角色访问控制,同时引入其内置速率限制器,减少了 30% 的暴力破解尝试。[1] 这种渐进策略避免了数据迁移风险,并允许并行运行旧新系统。

迁移步骤:从准备到桥接

迁移开始于最小化变更的评估。首先,解析现有 Auth.js 配置,识别核心组件:session 策略(JWT 或数据库)、提供者(OAuth/credentials)和回调钩子。Better Auth 的框架无关性意味着无需特定框架适配,但需选择合适的数据库适配器。

  1. 环境与依赖准备
    移除 Auth.js 依赖:npm uninstall next-auth。安装 Better Auth:npm install better-auth。配置环境变量,包括 BETTER_AUTH_SECRET(使用 openssl rand -base64 32 生成)和 BETTER_AUTH_URL(应用基 URL)。对于数据库,选择适配器如 Drizzle:npm install drizzle-orm better-auth/adapters/drizzle。生成初始 schema:npx @better-auth/cli generate。这会自动创建用户、会话和账户表,支持自动迁移。

  2. 保留 OAuth 和凭证流
    Better Auth 原生支持 email/password 和社交登录。配置 auth.ts 文件:

    import { betterAuth } from "better-auth";
    import { drizzleAdapter } from "better-auth/adapters/drizzle";
    import { db } from "./db"; // 你的 Drizzle 实例
    
    export const auth = betterAuth({
      database: drizzleAdapter(db, { provider: "pg" }), // 假设 PostgreSQL
      emailAndPassword: { enabled: true },
      socialProviders: {
        google: {
          clientId: process.env.GOOGLE_CLIENT_ID!,
          clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
        },
        // 其他 OAuth 提供者
      },
    });
    

    这保留了 Auth.js 的核心流。自定义提供者钩子允许扩展:使用 mapProfileToUser 函数映射 OAuth profile 到用户模型,例如添加自定义字段如 roles 以兼容旧系统。

  3. 零停机会话桥接
    零停机是迁移的关键。通过自定义中间件桥接 Auth.js 和 Better Auth 的会话。实现一个 session 桥接器:在 API 路由中检查旧 JWT 或 cookie,如果存在,使用钩子验证并生成新 Better Auth 会话。
    示例桥接钩子:

    // middleware.ts
    import { getToken } from "next-auth/jwt"; // 临时保留 Auth.js
    import { auth } from "./auth";
    
    export async function bridgeSession(req: Request) {
      const oldToken = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });
      if (oldToken && !req.headers.get("better-auth-session")) {
        // 验证旧 token 并创建新会话
        const newSession = await auth.api.createSession({
          userId: oldToken.sub,
          expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 天
        });
        // 设置新 cookie
        req.headers.set("Set-Cookie", `better-auth.session=${newSession.token}; HttpOnly; Secure`);
      }
      return req;
    }
    

    部署时,使用蓝绿部署:新版本路由渐进接管旧流量。监控桥接成功率,确保 >99% 用户无缝过渡。

  4. 自定义提供者钩子
    对于复杂 OAuth 流,使用 Better Auth 的钩子自定义验证逻辑。例如,在 GitHub 提供者中添加企业 SSO 检查:

    socialProviders: {
      github: {
        clientId: process.env.GITHUB_ID!,
        clientSecret: process.env.GITHUB_SECRET!,
        async authorize({ profile, tokens }) {
          // 自定义逻辑:检查企业邮箱
          if (profile.email?.endsWith("@company.com")) {
            return { user: { ...profile, verified: true } };
          }
          throw new Error("Unauthorized domain");
        },
      },
    }
    

    这确保了凭证流的安全,同时支持多因素认证插件。

可落地参数与清单

为确保迁移可靠,提供以下工程化参数和监控清单:

  • 超时与阈值:会话过期时间设为 30 天(session: { expirationTime: 30 * 24 * 60 * 60 }),OAuth token 刷新间隔 1 小时。速率限制:登录尝试限 5 次/分钟(rateLimiter: { max: 5, windowMs: 60000 })。
  • 数据库参数:使用连接池大小 20(Drizzle config),迁移阈值:表变更 <10 列时自动执行,回滚点设在事务开始前。
  • 监控要点:桥接失败率 <0.1%(使用 Prometheus 指标),会话迁移延迟 <100ms。日志:启用 debug: true 追踪钩子执行。
  • 回滚策略:如果桥接失败率 >1%,切换回 Auth.js 路由(Nginx 代理)。测试清单:单元测试钩子(Jest),端到端测试 OAuth 流(Playwright)。

潜在风险与缓解

迁移中主要风险是会话不兼容,导致用户注销。缓解:预迁移阶段运行影子模式,验证 100% 旧会话可桥接。另一个限是插件兼容:Better Auth 的 organization 插件可替换 Auth.js 的 roles,但需映射字段。总体,插件式方法将迁移时间从数周缩短至几天。

通过以上策略,从 Auth.js 到 Better Auth 的迁移不仅是技术升级,更是向更安全、可扩展系统的转变。开发者可根据项目规模调整参数,确保生产环境稳定。未来,随着 Better Auth 插件生态的丰富,这种迁移将更高效。

[1] Better Auth 官方文档:https://www.better-auth.com/docs
[2] 从 Auth.js 迁移指南(Juejin 文章)。

(字数:1028)