电子邮件 OTP

用于 Better Auth 的电子邮件 OTP 插件。

电子邮件 OTP 插件允许用户通过发送到其电子邮件地址的一次性密码(OTP)进行登录、验证电子邮件或重置密码。

安装

将插件添加到您的身份验证配置中

emailOTP 插件添加到您的身份验证配置,并实现 sendVerificationOTP() 方法。

auth.ts
import { betterAuth } from "better-auth"
import { emailOTP } from "better-auth/plugins"

export const auth = betterAuth({
    // ... 其他配置选项
    plugins: [
        emailOTP({ 
            async sendVerificationOTP({ email, otp, type }) { 
                if (type === "sign-in") { 
                    // 发送登录的 OTP
                } else if (type === "email-verification") { 
                    // 发送电子邮件验证的 OTP
                } else { 
                    // 发送密码重置的 OTP
                } 
            }, 
        }) 
    ]
})

添加客户端插件

auth-client.ts
import { createAuthClient } from "better-auth/client"
import { emailOTPClient } from "better-auth/client/plugins"

export const authClient = createAuthClient({
    plugins: [
        emailOTPClient() 
    ]
})

使用方法

发送 OTP

使用 sendVerificationOtp() 方法向用户的电子邮件地址发送 OTP。

POST/email-otp/send-verification-otp
const { data, error } = await authClient.emailOtp.sendVerificationOtp({    email: "user@example.com", // required    type: "sign-in", // required});
Parameters
emailstringrequired

发送 OTP 的电子邮件地址。

type"email-verification" | "sign-in" | "forget-password"required

OTP 类型。sign-inemail-verificationforget-password

校验 OTP(可选)

使用 checkVerificationOtp() 方法验证 OTP 是否有效。

POST/email-otp/check-verification-otp
const { data, error } = await authClient.emailOtp.checkVerificationOtp({    email: "user@example.com", // required    type: "sign-in", // required    otp: "123456", // required});
Parameters
emailstringrequired

发送 OTP 的电子邮件地址。

type"email-verification" | "sign-in" | "forget-password"required

OTP 类型。sign-inemail-verificationforget-password

otpstringrequired

发送到电子邮件的 OTP。

使用 OTP 登录

使用 OTP 登录时,先通过 sendVerificationOtp() 方法向用户电子邮件发送类型为 "sign-in" 的 OTP。

POST/email-otp/send-verification-otp
const { data, error } = await authClient.emailOtp.sendVerificationOtp({    email: "user@example.com", // required    type: "sign-in", // required});
Parameters
emailstringrequired

发送 OTP 的电子邮件地址。

type"sign-in"required

OTP 类型。

用户提供 OTP 后,可使用 signIn.emailOtp() 方法登录用户。

POST/sign-in/email-otp
const { data, error } = await authClient.signIn.emailOtp({    email: "user@example.com", // required    otp: "123456", // required    name: "John Doe",    image: "https://example.com/image.png",});
Parameters
emailstringrequired

登录的电子邮件地址。

otpstringrequired

发送到电子邮件的 OTP。

namestring

用户显示名称,仅在用户首次注册时使用。

imagestring

用户头像 URL,仅在用户首次注册时使用。

如果用户未注册,将自动完成注册。已配置的额外字段 也会被接受用于新用户。若想禁止自动注册,可在选项中传入 disableSignUptrue

使用 OTP 验证电子邮件

使用 OTP 验证用户邮箱时,先通过 sendVerificationOtp() 方法向用户邮箱发送类型为 "email-verification" 的 OTP。

POST/email-otp/send-verification-otp
const { data, error } = await authClient.emailOtp.sendVerificationOtp({    email: "user@example.com", // required    type: "email-verification", // required});
Parameters
emailstringrequired

发送 OTP 的电子邮件地址。

type"email-verification"required

OTP 类型。

用户输入 OTP 后,使用 verifyEmail() 方法完成邮箱验证。

POST/email-otp/verify-email
const { data, error } = await authClient.emailOtp.verifyEmail({    email: "user@example.com", // required    otp: "123456", // required});
Parameters
emailstringrequired

需要验证的电子邮件地址。

otpstringrequired

需要验证的 OTP。

使用 OTP 重置密码

使用 OTP 重置密码时,使用 emailOtp.requestPasswordReset() 方法向用户邮箱发送类型为 "forget-password" 的 OTP。

POST/email-otp/request-password-reset
const { data, error } = await authClient.emailOtp.requestPasswordReset({    email: "user@example.com", // required});
Parameters
emailstringrequired

发送 OTP 的电子邮件地址。

/forget-password/email-otp 端点已被弃用,请改为使用 /email-otp/request-password-reset

用户提供 OTP 后,可以选择使用 checkVerificationOtp() 方法验证 OTP 是否有效。

POST/email-otp/check-verification-otp
const { data, error } = await authClient.emailOtp.checkVerificationOtp({    email: "user@example.com", // required    type: "forget-password", // required    otp: "123456", // required});
Parameters
emailstringrequired

发送 OTP 的电子邮件地址。

type"forget-password"required

OTP 类型。

otpstringrequired

发送到电子邮件的 OTP。

然后,使用 resetPassword() 方法重置用户密码。

POST/email-otp/reset-password
const { data, error } = await authClient.emailOtp.resetPassword({    email: "user@example.com", // required    otp: "123456", // required    password: "new-secure-password", // required});
Parameters
emailstringrequired

需要重置密码的电子邮件地址。

otpstringrequired

发送到电子邮件的 OTP。

passwordstringrequired

新密码。

使用 OTP 更改电子邮件

要允许用户使用 OTP 更改电子邮件,需先启用 changeEmail 功能,该功能默认关闭。将 changeEmail.enabled 设置为 true

auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
    plugins: [
        emailOTP({
            changeEmail: {
                enabled: true, 
            }
        })
    ]
})

默认情况下,当用户请求更改电子邮件时,OTP 会发送到新的电子邮件地址。只有用户验证了新邮箱后,邮箱才会被更新。

使用方法

要更改用户电子邮件地址,使用 emailOtp.requestEmailChange() 方法向用户新的电子邮件地址发送类型为 "change-email" 的 OTP。

POST/email-otp/request-email-change
const { data, error } = await authClient.emailOtp.requestEmailChange({    newEmail: "user@example.com", // required    otp: "123456",});
Parameters
newEmailstringrequired

新的电子邮件地址,用于接收 OTP。

otpstring

发送到当前邮箱的 OTP。当 changeEmail.verifyCurrentEmail 选项设置为 true 时,此项必填。

用户提供 OTP 后,使用 changeEmail() 方法更改用户邮箱地址。

POST/email-otp/change-email
const { data, error } = await authClient.emailOtp.changeEmail({    newEmail: "user@example.com", // required    otp: "123456", // required});
Parameters
newEmailstringrequired

要更改为的新邮箱地址。

otpstringrequired

发送到新邮箱的 OTP。

使用当前邮箱确认

为了增加安全性,您可以要求用户先通过发送到当前邮箱的 OTP 进行确认,再发送 OTP 到新邮箱。要启用此功能,请在插件选项中将 changeEmail.verifyCurrentEmail 设置为 true

auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
    plugins: [
        emailOTP({
            changeEmail: {
                enabled: true,
                verifyCurrentEmail: true, 
            }
        })
    ]
})

在请求邮箱更改前,使用类型为 email-verificationsendVerificationOtp() 方法向用户邮箱发送 OTP。

POST/email-otp/send-verification-otp
const { data, error } = await authClient.emailOtp.sendVerificationOtp({    email: "user@example.com", // required    type: "email-verification", // required});
Parameters
emailstringrequired

发送 OTP 的电子邮件地址。

typestringrequired

OTP 类型。确认邮箱更改时必须为 email-verification

然后,用户调用 requestEmailChange() 时提供该 OTP。系统会先验证发送到当前邮箱的 OTP,然后再发送 OTP 到新邮箱。

重写默认的电子邮件验证

要重写默认的电子邮件验证,可在选项中传入 overrideDefaultEmailVerification: true。此设置会让系统改用邮件 OTP 代替默认的验证链接来完成电子邮件验证。换言之,用户将通过输入 OTP 来验证邮箱,而不是点击链接。

auth.ts
import { betterAuth } from "better-auth";
import { emailOTP } from "better-auth/plugins"

export const auth = betterAuth({
  plugins: [
    emailOTP({
      overrideDefaultEmailVerification: true, 
      async sendVerificationOTP({ email, otp, type }) {
        // 实现 sendVerificationOTP 方法,向用户电子邮件发送 OTP
      },
    }),
  ],
});

选项

  • sendVerificationOTP:向用户邮箱发送 OTP 的函数。该函数接收包含以下属性的对象:

    • email:用户电子邮件地址。
    • otp:生成的 OTP。
    • type:OTP 类型,可为 "sign-in"、"email-verification" 或 "forget-password"。

    建议不要等待邮件发送完成以避免时序攻击。在无服务器平台上,使用 waitUntil 或类似方式确保邮件已发送。

  • otpLength:OTP 的长度。默认值为 6

  • expiresIn:OTP 过期时间(秒)。默认值为 300 秒。

auth.ts
import { betterAuth } from "better-auth"
import { emailOTP } from "better-auth/plugins"

export const auth = betterAuth({
    plugins: [
        emailOTP({
            otpLength: 8,
            expiresIn: 600
        })
    ]
})
  • sendVerificationOnSignUp:布尔值,决定用户注册时是否发送 OTP。默认值为 false

  • disableSignUp:布尔值,决定当用户未注册时是否禁止自动注册。默认值为 false

  • generateOTP:生成 OTP 的函数。默认生成一个随机 6 位数字。

  • allowedAttempts:允许验证 OTP 的最大尝试次数。默认值为 3。超过该次数后,OTP 失效,用户需重新请求。

auth.ts
import { betterAuth } from "better-auth"
import { emailOTP } from "better-auth/plugins"

export const auth = betterAuth({
    plugins: [
        emailOTP({
            allowedAttempts: 5, // 允许 5 次尝试后使 OTP 失效
            expiresIn: 300
        })
    ]
})

当超过最大尝试次数时,verifyOTPsignIn.emailOtpverifyEmailresetPassword 方法将返回错误,错误码为 TOO_MANY_ATTEMPTS

  • storeOTP:在数据库中存储 OTP 的方式,可选 encryptedhashedplain 文本。默认为明文存储。

注意:这不会影响发送给用户的 OTP,只影响数据库中存储的 OTP。

您也可以传入自定义的加密器或哈希器来存储 OTP。

自定义加密器

auth.ts
emailOTP({
    storeOTP: { 
        encrypt: async (otp) => {
            return myCustomEncryptor(otp);
        },
        decrypt: async (otp) => {
            return myCustomDecryptor(otp);
        },
    }
})

自定义哈希器

auth.ts
emailOTP({
    storeOTP: {
        hash: async (otp) => {
            return myCustomHasher(otp);
        },
    }
})