从 Auth.js 迁移到 Better Auth
从 Auth.js 迁移到 Better Auth 的分步指南。
介绍
在本指南中,我们将逐步演示如何将项目从 Auth.js(前身为 NextAuth.js)迁移到 Better Auth。由于这两个项目的设计理念不同,迁移需要仔细规划和实施。如果您当前的设置运行良好,则无需紧急迁移。我们仍然会为 Auth.js 处理安全补丁和关键问题。
但如果您正在启动新项目或在当前设置中遇到挑战,我们强烈建议使用 Better Auth。我们的路线图包括以前仅 Auth.js 才有的功能,我们希望这能加强生态系统的统一,而不会导致分裂。
创建 Better Auth 实例
在开始迁移过程之前,请在项目中设置 Better Auth。请按照安装指南开始。
例如,如果您使用 GitHub OAuth 提供商,以下是 auth.ts 文件的对比。
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/github"
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [GitHub],
})import { betterAuth } from "better-auth";
export const auth = betterAuth({
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
},
},
})Better Auth 现在支持无数据库的无状态会话管理。如果您之前在 Auth.js 中使用了数据库适配器,可以参阅下方的数据库模型来了解 Better Auth 核心模式的差异。
创建客户端实例
此客户端实例包含一组与 Better Auth 服务器实例交互的函数。详情请参见此处。
import { createAuthClient } from "better-auth/react"
export const authClient = createAuthClient()更新路由处理器
将 /app/api/auth/[...nextauth] 文件夹重命名为 /app/api/auth/[...all] 以避免混淆。然后更新 route.ts 文件如下:
import { handlers } from "@/lib/auth"
export const { GET, POST } = handlersimport { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";
export const { POST, GET } = toNextJsHandler(auth)会话管理
本节将对比 Auth.js 和 Better Auth 中的会话管理方式。详情请参见此处。
客户端
登入
以下是使用 GitHub OAuth 提供商时,Auth.js 与 Better Auth 登录用户的差异示例:
"use client"
import { signIn } from "next-auth/react"
signIn("github")"use client"
import { authClient } from "@/lib/auth-client";
const { data, error } = await authClient.signIn.social({
provider: "github",
})登出
以下是 Auth.js 和 Better Auth 用户登出的差异示例。
"use client"
import { signOut } from "next-auth/react"
signOut()"use client"
import { authClient } from "@/lib/auth-client";
const { data, error } = await authClient.signOut()获取会话
以下是 Auth.js 和 Better Auth 获取当前活动会话的差异示例。
"use client"
import { useSession } from "next-auth/react"
const { data, status, update } = useSession()"use client"
import { authClient } from "@/lib/auth-client";
const { data, error, refetch, isPending, isRefetching } = authClient.useSession()服务器端
登入
以下是使用 GitHub OAuth 提供商时,Auth.js 和 Better Auth 登录用户的差异示例:
import { signIn } from "@/lib/auth"
await signIn("github")import { auth } from "@/lib/auth";
const { redirect, url } = await auth.api.signInSocial({
body: {
provider: "github",
},
})登出
以下是 Auth.js 和 Better Auth 用户登出的差异示例。
import { signOut } from "@/lib/auth"
await signOut()import { auth } from "@/lib/auth";
import { headers } from "next/headers";
const { success } = await auth.api.signOut({
headers: await headers(),
})获取会话
以下是 Auth.js 和 Better Auth 获取当前活动会话的差异示例。
import { auth } from "@/lib/auth";
const session = await auth()import { auth } from "@/lib/auth";
import { headers } from "next/headers";
const session = await auth.api.getSession({
headers: await headers(),
})保护资源
Proxy(中间件)并非为慢速数据获取设计。虽然 Proxy 可用于权限检查类的乐观性校验(如基于权限的重定向),但不应作为完整的会话管理或授权解决方案。- Next.js 文档
Auth.js 提供了使用 Proxy(中间件)的方式,但我们建议在每个页面或路由里进行身份验证检查,而非在 Proxy 或 Layout 中。以下是使用 Better Auth 保护资源的基本示例。
"use client";
import { authClient } from "@/lib/auth-client";
import { redirect } from "next/navigation";
const DashboardPage = () => {
const { data, error, isPending } = authClient.useSession();
if (isPending) {
return <div>加载中</div>;
}
if (!data || error) {
redirect("/sign-in");
}
return (
<div>
<h1>欢迎 {data.user.name}</h1>
</div>
);
};
export default DashboardPage;import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
const DashboardPage = async () => {
const session = await auth.api.getSession({
headers: await headers(),
});
if (!session) {
redirect("/sign-in");
}
return (
<div>
<h1>欢迎 {session.user.name}</h1>
</div>
);
};
export default DashboardPage;数据库模型
Auth.js 和 Better Auth 都提供无状态(JWT)和数据库会话策略。如果您之前在 Auth.js 中使用数据库会话策略,并计划在 Better Auth 中继续使用,则需要迁移数据库。
正如 Auth.js 有数据库模型,Better Auth 也有核心模式。本节将对比两者并探讨差异。
User -> User
Session -> Session
Account -> Account
VerificationToken -> Verification
比较总结
表:User
- Better Auth 中
name、email和emailVerified字段为必填,Auth.js 中为可选 - Better Auth 使用布尔值表示
emailVerified,而 Auth.js 使用时间戳 - Better Auth 增加了
createdAt和updatedAt时间戳字段
表:Session
- Better Auth 使用
token替代sessionToken - Better Auth 使用
expiresAt替代expires - Better Auth 增加了
ipAddress和userAgent字段 - Better Auth 包括
createdAt和updatedAt时间戳
表:Account
- Better Auth 采用 camelCase 命名(如
refreshToken替代refresh_token) - Better Auth 增加了
accountId,用于区分账号外部 ID 和内部 ID - Better Auth 使用
providerId替代provider - Better Auth 增加了
accessTokenExpiresAt和refreshTokenExpiresAt用于令牌管理 - Better Auth 增加了
password字段,支持内建的凭证认证 - Better Auth 没有
type字段,其类型由providerId决定 - Better Auth 移除了
token_type和session_state字段 - Better Auth 增加了
createdAt和updatedAt时间戳
表:VerificationToken -> Verification
- Better Auth 使用
Verification表替代VerificationToken - Better Auth 使用单一
id作为主键,替代复合主键 - Better Auth 使用
value替代token,支持多种验证类型 - Better Auth 使用
expiresAt替代expires - Better Auth 增加了
createdAt和updatedAt时间戳
如果您使用的是 Auth.js v4,注意 v5 在数据库模式方面没有破坏性变更。如果您不使用 oauth_token_secret 和 oauth_token 等可选字段,可以删除它们。像 refresh_token_expires_in 这样的少用字段也可以移除。
自定义
如果您扩展了数据库模型或在 Auth.js 中实现了额外逻辑,Better Auth 允许您以类型安全的方式自定义核心模式。您还可以在数据库操作的生命周期中定义自定义逻辑。更多详情请参见概念 - 数据库。
总结
现在,您已准备好从 Auth.js 迁移到 Better Auth。欲了解包含多种认证方式的完整实现,请访问 Next.js Demo 应用。Better Auth 提供更灵活和更多功能,请务必探索文档以充分发挥其潜力。
如果您需要迁移帮助,欢迎加入我们的社区或联系 contact@better-auth.com。