mcpField
E
email-and-password-best-practices

email-and-password-best-practices

github.com/better-auth开发22747.5k 次安装8 周前更新
代码仓库

关于 email-and-password-best-practices

面向使用 Better Auth 实现邮箱和密码认证的开发者,介绍邮箱验证、密码重置、令牌处理、会话撤销、验证及密码哈希配置。

主要功能

  1. 01邮箱验证配置
  2. 02密码重置流程配置
  3. 03重置令牌期限与单次使用
  4. 04密码重置后撤销会话
  5. 05密码长度与哈希选项

适用场景

  1. 01为注册流程添加邮箱验证
  2. 02构建密码重置流程
  3. 03凭据变更后撤销会话
  4. 04选择自定义密码哈希函数

安装

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

$npx skills add https://github.com/better-auth/skills --skill email-and-password-best-practices

安装后在 Claude Code 中输入/email-and-password-best-practices确认已加载。

详细介绍

快速开始

  1. 启用邮箱/密码:emailAndPassword: { enabled: true }
  2. 配置 emailVerification.sendVerificationEmail
  3. 为密码重置流程添加 sendResetPassword
  4. 运行 npx auth@latest migrate
  5. 验证:尝试注册并确认验证邮件已触发

邮箱验证设置

配置 emailVerification.sendVerificationEmail 以验证用户的邮箱地址。

import { betterAuth } from "better-auth";
import { sendEmail } from "./email"; // your email sending function

export const auth = betterAuth({
  emailVerification: {
    sendVerificationEmail: async ({ user, url, token }, request) => {
      await sendEmail({
        to: user.email,
        subject: "Verify your email address",
        text: `Click the link to verify your email: ${url}`,
      });
    },
  },
});

注意:url 参数包含完整的验证链接。如果需要构建自定义验证 URL,可以使用 token。

要求邮箱验证

为了提高安全性,启用 emailAndPassword.requireEmailVerification,在用户验证邮箱之前阻止其登录。启用后,未验证的用户每次尝试登录时都会收到一封新的验证邮件。

export const auth = betterAuth({
  emailAndPassword: {
    requireEmailVerification: true,
  },
});

注意:这要求配置 sendVerificationEmail,且仅适用于邮箱/密码登录。

客户端验证

实现客户端验证,以便立即向用户提供反馈并减少服务器负载。

回调 URL

在注册和登录请求中,回调 URL 始终使用绝对 URL(包含来源地址)。这样可以避免 Better Auth 推断来源地址,从而防止后端和前端位于不同域名时出现问题。

const { data, error } = await authClient.signUp.email({
  callbackURL: "https://example.com/callback", // absolute URL with origin
});

密码重置流程

在邮箱和密码配置中提供 sendResetPassword,以启用密码重置功能。

import { betterAuth } from "better-auth";
import { sendEmail } from "./email"; // your email sending function

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    // Custom email sending function to send reset-password email
    sendResetPassword: async ({ user, url, token }, request) => {
      void sendEmail({
        to: user.email,
        subject: "Reset your password",
        text: `Click the link to reset your password: ${url}`,
      });
    },
    // Optional event hook
    onPasswordReset: async ({ user }, request) => {
      // your logic here
      console.log(`Password for user ${user.email} has been reset.`);
    },
  },
});
安全注意事项

内置保护措施:后台发送邮件(防止计时攻击)、对无效请求执行虚假操作,以及无论用户是否存在都返回相同的响应消息。

在无服务器平台上,配置后台任务处理程序:

export const auth = betterAuth({
  advanced: {
    backgroundTasks: {
      handler: (promise) => {
        // Use platform-specific methods like waitUntil
        waitUntil(promise);
      },
    },
  },
});
令牌安全

令牌默认在 1 小时后过期。使用 resetPasswordTokenExpiresIn 配置有效期(以秒为单位):

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    resetPasswordTokenExpiresIn: 60 * 30, // 30 minutes
  },
});

令牌只能使用一次——成功重置后会立即删除。

会话撤销

启用 revokeSessionsOnPasswordReset,以便在密码重置时使所有现有会话失效:

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    revokeSessionsOnPasswordReset: true,
  },
});
密码要求

密码长度限制(可配置):

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    minPasswordLength: 12,
    maxPasswordLength: 256,
  },
});
发送密码重置邮件

调用 requestPasswordReset 发送重置链接。这会触发配置中的 sendResetPassword 函数。

const data = await auth.api.requestPasswordReset({
  body: {
    email: "[email protected]", // required
    redirectTo: "https://example.com/reset-password",
  },
});

或使用 authClient:

const { data, error } = await authClient.requestPasswordReset({
  email: "[email protected]", // required
  redirectTo: "https://example.com/reset-password",
});

注意:虽然必须提供 email,但我们也建议配置 redirectTo,以提供更顺畅的用户体验。

密码哈希

默认算法:scrypt(Node.js 原生支持,无需外部依赖)。

自定义哈希算法

如需使用 Argon2id 或其他算法,请提供自定义的 hash 和 verify 函数:

import { betterAuth } from "better-auth";
import { hash, verify, type Options } from "@node-rs/argon2";

const argon2Options: Options = {
  memoryCost: 65536, // 64 MiB
  timeCost: 3, // 3 iterations
  parallelism: 4, // 4 parallel lanes
  outputLen: 32, // 32 byte output
  algorithm: 2, // Argon2id variant
};

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    password: {
      hash: (password) => hash(password, argon2Options),
      verify: ({ password, hash: storedHash }) =>
        verify(storedHash, password, argon2Options),
    },
  },
});

注意:如果在现有系统中切换哈希算法,使用旧算法进行密码哈希的用户将无法登录。如有需要,请规划迁移策略。

评论

支持 Markdown