邮箱和密码

邮箱和密码认证是许多应用程序常用的方法。Better Auth 提供了一个内置的邮箱和密码认证器,你可以轻松地将其集成到你的项目中。

如果你更喜欢基于用户名的认证,可以查看 用户名插件。它扩展了邮箱和密码认证器,增加了用户名支持。

启用邮箱和密码认证

要启用邮箱和密码认证,你需要在 auth 配置中将 emailAndPassword.enabled 选项设置为 true

auth.ts
import { betterAuth } from "better-auth";
 
export const auth = betterAuth({
  emailAndPassword: { 
    enabled: true, 
  }, 
});

如果未启用,将不允许你使用邮箱和密码进行登录或注册。

使用方法

注册

要注册用户,你可以使用客户端提供的 signUp.email 函数。signUp 函数接受一个包含以下属性的对象:

  • email:用户的邮箱地址。
  • password:用户的密码。默认情况下,密码长度至少为 8 个字符,最多为 32 个字符。
  • name:用户的名称。
  • image:用户的头像。(可选)
auth-client.ts
const { data, error } = await authClient.signUp.email({
  email: "[email protected]",
  password: "password1234",
  name: "test",
  image: "https://example.com/image.png",
});

登录

要登录用户,你可以使用客户端提供的 signIn.email 函数。signIn 函数接受一个包含以下属性的对象:

  • email:用户的邮箱地址。
  • password:用户的密码。
  • rememberMe:如果为 false,当浏览器关闭时用户将被登出。(可选)(默认:true)
  • callbackURL:用户登录后重定向的 URL。(可选)
auth-client.ts
const { data, error } = await authClient.signIn.email({
  email: "[email protected]",
  password: "password1234",
});

登出

要登出用户,你可以使用客户端提供的 signOut 函数。

auth-client.ts
await authClient.signOut();

你可以传递 fetchOptions 来在成功时重定向

auth-client.ts
await authClient.signOut({
  fetchOptions: {
    onSuccess: () => {
      router.push("/login"); // 重定向到登录页面
    },
  },
});

邮箱验证

要启用邮箱验证,你需要传递一个发送验证邮件的函数。sendVerificationEmail 函数接受一个数据对象,包含以下属性:

  • user:用户对象。
  • url:发送给用户的包含令牌的 URL。
  • token:用于完成邮箱验证的验证令牌。

以及一个 request 对象作为第二个参数。

auth.ts
import { betterAuth } from "better-auth";
import { sendEmail } from "./email"; // 你的邮件发送函数
 
export const auth = betterAuth({
  emailVerification: {
    sendVerificationEmail: async ( { user, url, token }, request) => {
      await sendEmail({
        to: user.email,
        subject: "验证你的邮箱地址",
        text: `点击链接验证你的邮箱:${url}`,
      });
    },
  },
});

在客户端,你可以使用 sendVerificationEmail 函数向用户发送验证链接。这将触发你在 auth 配置中提供的 sendVerificationEmail 函数。

当用户点击邮件中的链接时,如果令牌有效,用户将被重定向到 callbackURL 参数中提供的 URL。如果令牌无效,用户将被重定向到 callbackURL 参数中提供的 URL,并在查询字符串中包含错误信息 ?error=invalid_token

要求邮箱验证

如果你启用了要求邮箱验证,用户必须在登录前验证他们的邮箱。每次用户尝试登录时,都会调用 sendVerificationEmail。

这只有在实现了 sendVerificationEmail 并且用户尝试使用邮箱和密码登录时才有效。

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

如果用户尝试在未验证邮箱的情况下登录,你可以处理错误并向用户显示消息。

auth-client.ts
await authClient.signIn.email(
  {
    email: "[email protected]",
    password: "password",
  },
  {
    onError: (ctx) => {
      // 处理错误
      if (ctx.error.status === 403) {
        alert("请验证你的邮箱地址");
      }
      //你也可以显示原始错误消息
      alert(ctx.error.message);
    },
  }
);

手动触发邮箱验证

你可以通过调用 sendVerificationEmail 函数手动触发邮箱验证。

await authClient.sendVerificationEmail({
  email: "[email protected]",
  callbackURL: "/", // 验证后的重定向 URL
});

忘记密码

要允许用户重置密码,首先你需要向邮箱和密码认证器提供 sendResetPassword 函数。sendResetPassword 函数接受一个数据对象,包含以下属性:

  • user:用户对象。
  • url:发送给用户的包含令牌的 URL。
  • token:用于完成密码重置的验证令牌。

以及一个 request 对象作为第二个参数。

auth.ts
import { betterAuth } from "better-auth";
import { sendEmail } from "./email"; // 你的邮件发送函数
 
export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    sendResetPassword: async ({user, url, token}, request) => {
      await sendEmail({
        to: user.email,
        subject: "重置你的密码",
        text: `点击链接重置你的密码:${url}`,
      });
    },
  },
});

配置好服务器后,你可以调用 forgetPassword 函数向用户发送重置密码链接。如果用户存在,它将触发你在 auth 配置中提供的 sendResetPassword 函数。

它接受一个包含以下属性的对象:

  • email:用户的邮箱地址。
  • redirectTo:用户点击邮件中的链接后重定向的 URL。如果令牌有效,用户将被重定向到此 URL,并在查询字符串中包含令牌。如果令牌无效,用户将被重定向到此 URL,并在查询字符串中包含错误信息 ?error=invalid_token
auth-client.ts
const { data, error } = await authClient.forgetPassword({
  email: "[email protected]",
  redirectTo: "/reset-password",
});

当用户点击邮件中的链接时,他们将被重定向到重置密码页面。你可以将重置密码页面添加到你的应用中。然后你可以使用 resetPassword 函数来重置密码。它接受一个包含以下属性的对象:

  • newPassword:用户的新密码。
auth-client.ts
const token = new URLSearchParams(window.location.search).get("token");
if (!token) {
  // 处理错误
}
const { data, error } = await authClient.resetPassword({
  newPassword: "password1234",
  token,
});

更新密码

这只能在服务器端工作,以下代码可能会随时间变化。

要设置密码,你必须先对其进行哈希处理:

const ctx = await auth.$context;
const hash = await ctx.password.hash("your-new-password");

然后,设置密码:

await ctx.internalAdapter.updatePassword("userId", hash) //(你也可以直接使用你的 orm)

配置

密码

Better Auth 将密码存储在 account 表中,providerId 设置为 credential

密码哈希:Better Auth 使用 scrypt 来哈希密码。scrypt 算法设计为缓慢且内存密集,以使攻击者难以暴力破解密码。OWASP 建议在 argon2id 不可用时使用 scrypt。我们决定使用 scrypt 是因为它由 Node.js 原生支持。

你可以通过在 auth 配置中设置 passwordHasher 选项来传递自定义密码哈希算法。

auth.ts
import { betterAuth } from "better-auth"
import { scrypt } from "scrypt"
 
export const auth = betterAuth({
    //...其他选项
    emailAndPassword: {
        password: {
            hash: // 你的自定义密码哈希函数
            verify: // 你的自定义密码验证函数
        }
    }
})
PropTypeDefault
enabled?
boolean
false
disableSignUp?
boolean
false
minPasswordLength?
number
8
maxPasswordLength?
number
128
sendResetPassword?
function
-
resetPasswordTokenExpiresIn?
number
3600
password?
object
-

On this page