电话号码
电话号码插件通过允许用户使用电话号码进行登录和注册来扩展身份验证系统。它包括用于验证电话号码的一次性密码(OTP)功能。
【The phone number plugin extends the authentication system by allowing users to sign in and sign up using their phone number. It includes OTP (One-Time Password) functionality to verify phone numbers.】
安装
【Installation】
将插件添加到服务器
import { betterAuth } from "better-auth"
import { phoneNumber } from "better-auth/plugins"
const auth = betterAuth({
plugins: [
phoneNumber({
sendOTP: ({ phoneNumber, code }, ctx) => {
// Implement sending OTP code via SMS
}
})
]
})Migrate the database
运行迁移或生成架构,以向数据库添加必要的字段和表。
npx @better-auth/cli migratenpx @better-auth/cli generateSee the Schema section to add the fields manually.
Add the client plugin
import { createAuthClient } from "better-auth/client"
import { phoneNumberClient } from "better-auth/client/plugins"
const authClient = createAuthClient({
plugins: [
phoneNumberClient()
]
})用法
【Usage】
发送验证码以进行验证
【Send OTP for Verification】
要将一次性密码(OTP)发送到用户的电话号码以进行验证,你可以使用 sendVerificationCode 接口。
【To send an OTP to a user's phone number for verification, you can use the sendVerificationCode endpoint.】
const { data, error } = await authClient.phoneNumber.sendOtp({ phoneNumber: "+1234567890", // required});| Prop | Description | Type |
|---|---|---|
phoneNumber | Phone number to send OTP. | string |
验证手机号
【Verify Phone Number】
发送一次性密码后,用户可以通过提供验证码来验证他们的电话号码。
【After the OTP is sent, users can verify their phone number by providing the code.】
const { data, error } = await authClient.phoneNumber.verify({ phoneNumber: "+1234567890", // required code: "123456", // required disableSession: false, updatePhoneNumber: true,});| Prop | Description | Type |
|---|---|---|
phoneNumber | Phone number to verify. | string |
code | OTP code. | string |
disableSession? | Disable session creation after verification. | boolean |
updatePhoneNumber? | Check if there is a session and update the phone number. | boolean |
当电话号码被验证时,用户表中的 phoneNumberVerified 字段会被设置为 true。如果 disableSession 没有被设置为 true,将会为用户创建一个会话。此外,如果提供了 callbackOnVerification,它将会被调用。
允许使用手机号注册
【Allow Sign-Up with Phone Number】
为了允许用户使用手机号码注册,你可以在插件配置中传递 signUpOnVerification 选项。这要求你传递 getTempEmail 函数以为用户生成临时电子邮箱。
【To allow users to sign up using their phone number, you can pass signUpOnVerification option to your plugin configuration. It requires you to pass getTempEmail function to generate a temporary email for the user.】
export const auth = betterAuth({
plugins: [
phoneNumber({
sendOTP: ({ phoneNumber, code }, ctx) => {
// Implement sending OTP code via SMS
},
signUpOnVerification: {
getTempEmail: (phoneNumber) => {
return `${phoneNumber}@my-site.com`
},
//optionally, you can also pass `getTempName` function to generate a temporary name for the user
getTempName: (phoneNumber) => {
return phoneNumber //by default, it will use the phone number as the name
}
}
})
]
})我们强烈建议不要等待 sendOTP 函数。如果你使用 await,它会使请求变慢,并可能导致时间攻击。在无服务器平台上,你可以使用 waitUntil 来确保 OTP 被发送。
使用手机号登录
【Sign In with Phone Number】
除了使用发送验证流程登录用户之外,你还可以使用手机号作为标识符,并通过手机号和密码登录用户。
【In addition to signing in a user using send-verify flow, you can also use phone number as an identifier and sign in a user using phone number and password.】
const { data, error } = await authClient.signIn.phoneNumber({ phoneNumber: "+1234567890", // required password, // required rememberMe: true,});| Prop | Description | Type |
|---|---|---|
phoneNumber | Phone number to sign in. | string |
password | Password to use for sign in. | string |
rememberMe? | Remember the session. | boolean |
更新电话号码
【Update Phone Number】
更新电话号码的过程与验证电话号码的过程相同。用户将收到一个 OTP 码来验证新的电话号码。
【Updating phone number uses the same process as verifying a phone number. The user will receive an OTP code to verify the new phone number.】
await authClient.phoneNumber.sendOtp({
phoneNumber: "+1234567890" // New phone number
})然后使用 OTP 码验证新的手机号码。
【Then verify the new phone number with the OTP code. 】
const isVerified = await authClient.phoneNumber.verify({
phoneNumber: "+1234567890",
code: "123456",
updatePhoneNumber: true // Set to true to update the phone number
})如果用户会话存在,电话号码将会自动更新。
【If a user session exist the phone number will be updated automatically.】
禁用会话创建
【Disable Session Creation】
默认情况下,插件在验证手机号码后会为用户创建会话。你可以通过在 verify 方法中传入 disableSession: true 来禁用此行为。
【By default, the plugin creates a session for the user after verifying the phone number. You can disable this behavior by passing disableSession: true to the verify method.】
const isVerified = await authClient.phoneNumber.verify({
phoneNumber: "+1234567890",
code: "123456",
disableSession: true
})请求重置密码
【Request Password Reset】
要使用 phoneNumber 启动请求密码重置流程,可以先在客户端调用 requestPasswordReset,将 OTP 代码发送到用户的手机号码。
【To initiate a request password reset flow using phoneNumber, you can start by calling requestPasswordReset on the client to send an OTP code to the user's phone number.】
const { data, error } = await authClient.phoneNumber.requestPasswordReset({ phoneNumber: "+1234567890", // required});| Prop | Description | Type |
|---|---|---|
phoneNumber | The phone number which is associated with the user. | string |
然后,你可以通过在客户端使用 OTP 代码和新密码调用 resetPassword 来重置密码。
【Then, you can reset the password by calling resetPassword on the client with the OTP code and the new password.】
const { data, error } = await authClient.phoneNumber.resetPassword({ otp: "123456", // required phoneNumber: "+1234567890", // required newPassword: "new-and-secure-password", // required});| Prop | Description | Type |
|---|---|---|
otp | The one time password to reset the password. | string |
phoneNumber | The phone number to the account which intends to reset the password for. | string |
newPassword | The new password. | string |
选项
【Options】
otpLength
要生成的 OTP 代码的长度。默认值为 6。
【The length of the OTP code to be generated. Default is 6.】
sendOTP
一个将 OTP 代码发送到用户电话号码的功能。它以电话号码和 OTP 代码作为参数。
【A function that sends the OTP code to the user's phone number. It takes the phone number and the OTP code as arguments.】
expiresIn
OTP 代码到期的时间,以秒为单位。默认值为300秒。
【The time in seconds after which the OTP code expires. Default is 300 seconds.】
callbackOnVerification
在电话号码验证后调用的函数。它将电话号码和用户对象作为第一个参数,将请求对象作为第二个参数。
【A function that is called after the phone number is verified. It takes the phone number and the user object as the first argument and a request object as the second argument.】
export const auth = betterAuth({
plugins: [
phoneNumber({
sendOTP: ({ phoneNumber, code }, ctx) => {
// Implement sending OTP code via SMS
},
callbackOnVerification: async ({ phoneNumber, user }, ctx) => {
// Implement callback after phone number verification
}
})
]
})sendPasswordResetOTP
一个将 OTP 代码发送到用户手机号码以重置密码的功能。它以手机号码和 OTP 代码作为参数。
【A function that sends the OTP code to the user's phone number for password reset. It takes the phone number and the OTP code as arguments.】
phoneNumberValidator
一个用于验证电话号码的自定义函数。它接受电话号码作为参数,并返回一个布尔值,表示电话号码是否有效。
【A custom function to validate the phone number. It takes the phone number as an argument and returns a boolean indicating whether the phone number is valid.】
verifyOTP
一个用于验证 OTP 码的自定义函数。当提供该函数时,将使用它来替代默认的内部验证逻辑。当你想要与处理 OTP 验证的外部短信提供商(例如 Twilio Verify、AWS SNS)集成时,这非常有用。该函数接收一个包含 phoneNumber 和 code 属性的对象以及一个请求对象,并返回一个布尔值或一个解析为布尔值的 Promise,用于指示 OTP 是否有效。
【A custom function to verify the OTP code. When provided, this function will be used instead of the default internal verification logic. This is useful when you want to integrate with external SMS providers that handle OTP verification (e.g., Twilio Verify, AWS SNS). The function takes an object with phoneNumber and code properties and a request object, and returns a boolean or a promise that resolves to a boolean indicating whether the OTP is valid.】
export const auth = betterAuth({
plugins: [
phoneNumber({
sendOTP: ({ phoneNumber, code }, ctx) => {
// Send OTP via your SMS provider
},
verifyOTP: async ({ phoneNumber, code }, ctx) => {
// Verify OTP with your desired logic (e.g., Twilio Verify)
// This is just an example, not a real implementation.
const isValid = await twilioClient.verify
.services('YOUR_SERVICE_SID')
.verificationChecks
.create({ to: phoneNumber, code });
return isValid.status === 'approved';
}
})
]
})使用此选项时,请确保已实现适当的验证,因为它会覆盖我们的内部验证逻辑。
signUpOnVerification
一个具有以下属性的对象:
getTempEmail:一个为用户生成临时邮箱的函数。它以电话号码作为参数,并返回临时邮箱。getTempName:一个为用户生成临时名称的函数。它以电话号码作为参数,并返回临时名称。
【An object with the following properties:
getTempEmail: A function that generates a temporary email for the user. It takes the phone number as an argument and returns the temporary email.getTempName: A function that generates a temporary name for the user. It takes the phone number as an argument and returns the temporary name.】
requireVerification
启用后,用户在手机号码未验证之前不能使用手机号码登录。如果未验证的用户尝试登录,服务器将响应 401 错误(PHONE_NUMBER_NOT_VERIFIED),并自动触发一次 OTP 发送以开始验证流程。
【When enabled, users cannot sign in with their phone number until it has been verified. If an unverified user attempts to sign in, the server will respond with a 401 error (PHONE_NUMBER_NOT_VERIFIED) and automatically trigger an OTP send to start the verification process.】
架构
【Schema】
该插件需要在用户表中添加两个字段
【The plugin requires 2 fields to be added to the user table 】
用户表
【User Table】
| Field Name | Type | Key | Description |
|---|---|---|---|
| phoneNumber | string | The phone number of the user | |
| phoneNumberVerified | boolean | Whether the phone number is verified or not |
OTP 验证尝试
【OTP Verification Attempts】
电话号码插件通过限制每个一次性密码(OTP)代码的验证尝试次数,内置了防止暴力破解攻击的保护功能。
【The phone number plugin includes a built-in protection against brute force attacks by limiting the number of verification attempts for each OTP code.】
phoneNumber({
allowedAttempts: 3, // default is 3
// ... other options
})当用户超过允许的验证尝试次数时:
- OTP 码会被自动删除
- 进一步的验证尝试将返回 403(禁止访问)状态,并显示“尝试次数过多”消息
- 用户需要请求一个新的 OTP 码以继续
【When a user exceeds the allowed number of verification attempts:
- The OTP code is automatically deleted
- Further verification attempts will return a 403 (Forbidden) status with "Too many attempts" message
- The user will need to request a new OTP code to continue】
超过尝试次数后的示例错误响应:
【Example error response after exceeding attempts:】
{
"error": {
"status": 403,
"message": "Too many attempts"
}
}收到 403 状态时,提示用户请求新的 OTP 验证码