Logo文档
注册登录鉴权指南

概述

学习如何在 NEXTDEVKIT 中使用 Better Auth 设置和使用身份验证

在有了数据库的基础后,我们就可以基于数据库来搭建出登录注册系统。

NextDevKit 提供了多种 Auth 的配置和使用方式,你可以根据你的需求选择合适的方式。

为什么使用 Better Auth

其实除了自己通过 auth 库来实现登录注册功能外,还有一些云产品也提供了 Auth 功能,例如 Clerk, Supabase auth,Auth0 等。

这些产品通常提供了更丰富的功能,并且可以方便集成。主要问题一是收费挺高的,一般按照你的 MAU(月活跃用户数)来收费,第二是需要你将用户数据存储到他们的数据库中,未来的迁移成本很高,等于完全与平台绑定。

NextDevKit 为了通用性而言,并没有选择任意云平台去绑定,而是选择了 Better Auth 作为默认的 Auth 库自己实现登录注册等功能。

Better Auth 是一个开源的 Auth 库,它提供了丰富的功能,并且可以方便集成,并且提供了丰富的插件生态和 OAuth 支持。

Better Auth 的优势:

  • 框架无关性 - 支持 React、Vue、Svelte、Next.js、Nuxt、Solid、Astro、Hono 等多种框架
  • 内置安全功能 - 自带双因子认证(2FA)、多租户、速率限制、CSRF 保护等
  • 开发体验友好 - 自动生成模式、完全类型安全、启用高级功能所需代码最少
  • 插件系统 - 可扩展功能,无需复杂的变通方法
  • TypeScript 优先 - 专为 TypeScript 构建,类型安全性更好

如何使用 Better Auth

配置 .env 文件

在 NextDevKit 中,我们默认使用 BETTER_AUTH_URL 和 BETTER_AUTH_SECRET 环境变量来配置 Better Auth。

第一个 BETTER_AUTH_URL 是指你的应用的 URL,例如本地环境 http://localhost:3000 或者生产环境的 https://your-app.com。

第二个 BETTER_AUTH_SECRET 是你的应用的 secret key,你可以通过 openssl rand -base64 32 命令来生成一个随机的 secret key。注意本地环境和生产环境的 secret key 尽量保持不一样。

配置 auth.ts 文件

Better Auth 需要你在 src/lib/auth.ts 文件中配置好对应的 login, register, forgot password, email verification 等功能的配置。

NextDevKit 已经默认配置好了一套最常用的 Better Auth 的配置,你只需要在 src/lib/auth.ts 文件中修改你需要的配置即可。

src/lib/auth.ts
export const auth = betterAuth({
	baseURL: getBaseUrl(), // 你的应用的 URL
	trustedOrigins: [getBaseUrl()],
	database: drizzleAdapter(db, { // 默认集成 drizzle 数据库
		provider: "pg", // 不同模板的数据库有所区别
		schema: { // 默认集成数据库对应的 schema
			user: user, // 用户表
			session: session, // 会话表
			account: account, // 账号表
			verification: verification, // 验证表
		},
	}),
	session: { 
		cookieCache: { // 默认开启 cookie 缓存
			enabled: true,
			maxAge: 5 * 60, // 缓存 5 分钟
		},
		expiresIn: 60 * 60 * 24 * 7, // 默认 7 天
		updateAge: 60 * 60 * 24, // 默认 1 天
		freshAge: 0, // 默认 0 秒
	},
	user: {
		deleteUser: { // 默认开启删除用户功能
			enabled: true,
		},
		additionalFields: { // 额外添加两个字段在 user 表中,可以根据你的需求添加更多的字段
			locale: { // 用户所选择的语言,在登录后会自动设置到 cookie 中
				type: "string",
				required: false,
			},
			customerId: { // 用户客户 ID
				type: "string",
				required: false,
			},
		},
		changeEmail: { // 默认开启修改邮箱功能
			enabled: true,
			sendChangeEmailVerification: async (
				{ user: { email, name }, url },
				request,
			) => {
				await sendEmail();
			},
		},
	},
	emailAndPassword: { // 默认开启 Email + Password 登录和注册功能
		enabled: true,
		requireEmailVerification: true,
		sendResetPassword: async ({ user: { email, name }, url }, request) => {
			await sendEmail();
		},
	},
	emailVerification: { // 默认开启邮箱验证功能,关闭后用户注册后不需要验证邮箱
		sendOnSignUp: true,
		autoSignInAfterVerification: true,
		sendVerificationEmail: async ({ user: { email, name }, url }, request) => {
			await sendEmail();
		},
	},
	account: {
		accountLinking: { // 默认开启账号关联功能,允许用户关联多个账号
			enabled: true,
			trustedProviders: ["google", "github"],
		},
	},
	socialProviders: { // 默认集成 Google 和 Github 的社交登录功能
		google: {
			clientId: process.env.GOOGLE_CLIENT_ID as string,
			clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
			scope: ["email", "profile"],
		},
		github: {
			clientId: process.env.GITHUB_CLIENT_ID as string,
			clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
		},
	},
	plugins: [admin()], // 默认开启 admin 插件,允许你通过 role 来区分 user
	onAPIError: {
		onError(error, ctx) {
			console.error(error, { ctx });
		},
	},
});

export type Session = typeof auth.$Infer.Session;

如上面的代码实例,NextDevKit 默认配置集成了两种登录和注册的方式,分别是 Email + Password 的方式,和社交登录的方式。

如上面的注释所示,NextDevKit 默认配置集成了多种功能,你可以根据你的需求选择合适的功能。

目前有的功能包括:

  • 默认开启 Email + Password 登录和注册功能
  • 默认开启邮箱验证功能,关闭后用户注册后不需要验证邮箱
  • 默认开启账号关联功能,允许用户关联多个账号
  • 默认集成 Google 和 Github 的社交登录功能
  • 默认开启 admin 插件,允许你通过 role 来区分 user
  • 默认开启 cookie 缓存,允许你通过 cookie 来缓存用户信息
  • 默认开启删除用户功能,允许你删除用户
  • 默认开启修改邮箱功能,允许你修改用户邮箱

强烈建议你阅读 Better Auth 的文档,来了解 Better Auth 的更多功能和配置。

其它比较常见的功能改动包括:

  • 禁用 Email + Password 登录和注册功能
  • 添加更多的社交登录集成
  • 开启 Two Factor Authentication 双重认证功能
  • 开启 Magic Link 登录功能
  • 开启手机号登录功能
  • 加入 Passkey 设备认证功能等

这些功能你可以根据需求和官方文档来进行配置和添加。

邮箱登录

通过邮箱登录的功能需要你配置好对应的邮箱服务,例如 Resend 的 API 密钥 RESEND_API_KEY,目前 NextDevKit 默认使用 Resend 来发送邮件。

因为邮箱登录注册需要开启邮箱验证,忘记密码,重置密码等功能,所以发送邮件对于邮箱登录注册功能来说是必须的。

目前 NextDevKit 默认只集成了 Resend 来发送邮件,你可以添加其它的邮箱服务。我们会在后面提到这一点。

NextDevKit 也已经配置了默认的邮箱验证,忘记密码,重置密码等邮件模板,你可以在 src/mail/templates 文件夹中找到对应的模板。也可以根据你的需求来优化对应的邮件模板。

社交登录

对于现代的 Web 应用来说,绝大多数人都会选择社交登录的方式进行登录。

所以社交登录的方式目前来说是必不可少的,反而是邮箱登录的方式可以考虑关闭。

配置 Google 登录

  1. 转到 Google Cloud Console
  2. 创建新项目或选择现有项目
  3. 导航到 "Credentials" → "Create Credentials" → "OAuth client ID"
  4. 如需要,配置 OAuth 同意屏幕
  5. 设置 OAuth 客户端 ID:
    • 应用程序类型:Web 应用程序
    • 已授权的 JavaScript 来源:https://your-domain.com
    • 已授权的重定向 URI:https://your-domain.com/api/auth/callback/google

如果是本地开发需要的话,记得将 http://localhost:3000 添加到 已授权的 JavaScript 来源中,并且将 http://localhost:3000/api/auth/callback/google 添加到 已授权的重定向 URI中。

添加到您的 .env 文件:

GOOGLE_CLIENT_ID="your_google_client_id"
GOOGLE_CLIENT_SECRET="your_google_client_secret"

3. 配置 GitHub OAuth

要启用 GitHub 身份验证:

  1. 转到 GitHub Developer Settings
  2. 点击 "OAuth Apps" → "New OAuth App"
  3. 填写注册表单:
    • 应用程序名称:NEXTDEVKIT
    • 主页 URL:https://your-domain.com(开发环境使用 http://localhost:3000)
    • 授权回调 URL:https://your-domain.com/api/auth/callback/github
  4. 复制 客户端 ID 和 客户端密钥

如果是本地开发需要的话,记得将 http://localhost:3000 添加到 主页 URL中,并且将 http://localhost:3000/api/auth/callback/github 添加到 授权回调 URL中。

添加到您的 .env 文件:

GITHUB_CLIENT_ID="your_github_client_id"
GITHUB_CLIENT_SECRET="your_github_client_secret"

💡 提示:为生产和开发环境创建不同的 OAuth 应用程序,使用不同的回调 URL。

添加其它社交登录

除了 Google 和 Github 外,Better Auth 还支持添加其它的社交登录,例如 Facebook, Twitter, Apple 等。

你可以在 Better Auth 的文档 下的 Authentication 中找到对应的配置方法。

在 NextDevKit 中,你可以首先在 src/lib/auth.ts 文件中添加其它的社交登录。配置对应的 clientId 和 clientSecret 等。

src/lib/auth.ts
socialProviders: {
	facebook: {
		clientId: process.env.FACEBOOK_CLIENT_ID as string,
		clientSecret: process.env.FACEBOOK_CLIENT_SECRET as string,

然后你可以在 src/config/oauth-provider.ts 文件中添加对应的社交登录还有对应的 icon 显示。这个地方的配置会影响到登录页面的显示。

src/config/oauth-provider.ts
export const oAuthProviders = {
	google: {
		name: "Google",
		icon: Google,
	},
	github: {
		name: "GitHub",
		icon: GitHub,
	},
} as const satisfies Record<
	string,
	{
		name: string;
		icon: JSXElementConstructor<React.SVGProps<SVGSVGElement>>;
	}
>;

export type OAuthProvider = keyof typeof oAuthProviders;

如果你想要深入了解 Social Providers 登录的机制,可以参考 SocialSignin 组件的实现和对应的官方文档。

src/components/auth/social-signin.tsx
const handleOAuthSignin = async (provider: OAuthProvider) => {
  try {
    setIsLoading(provider);

    await authClient.signIn.social({
      provider,
      callbackURL: `${window.location.origin}${redirectTo}`,
    });
  } catch (error) {
    console.error(`Error signing in with ${provider}:`, error);
  } finally {
    setIsLoading(null);
  }
};

🏗️ 身份验证架构

NEXTDEVKIT 的身份验证系统包括:

src/
├── lib/
│   ├── auth.ts           # 主要 Better Auth 配置
│   └── auth/
│       ├── server.ts     # 服务器端认证工具
│       ├── client.ts     # 客户端认证工具
│       ├── api.ts        # API 工具
│       ├── edge.ts       # Edge 运行时工具
│       └── errors.ts     # 认证错误处理
├── components/
│   └── auth/
│       ├── login-form.tsx
│       ├── signup-form.tsx
│       ├── social-signin.tsx
│       └── forgot-password-form.tsx