Phone number plugin installation on server
The phone number plugin is installed by importing it from 'better-auth/plugins' and passing it to the plugins array in betterAuth configuration. The plugin requires a sendOTP function that takes phoneNumber and code as parameters and handles sending the OTP via SMS.
Phone number plugin installation on client
The phone number client plugin is installed by importing phoneNumberClient from 'better-auth/client/plugins' and adding it to the plugins array in createAuthClient configuration.
Send OTP endpoint for phone number verification
POST endpoint at /phone-number/send-otp sends an OTP to a user's phone number. It requires a phoneNumber parameter of type string (example: '+1234567890').
Verify phone number endpoint
POST endpoint at /phone-number/verify verifies a phone number with an OTP code. Parameters: phoneNumber (string, required), code (string, required), disableSession (boolean, optional, default false), updatePhoneNumber (boolean, optional, default false to update existing user's phone number during active session).
Consume phone number OTP on server without creating session
The server-only method auth.api.consumePhoneNumberOTP({body: {phoneNumber, code}}) consumes an OTP without creating or updating a user or session. This is exposed through auth.api and does not register an HTTP route or generate an authClient method. It uses the same validation as verifyPhoneNumber but does not return a session or reusable proof of verification.
Sign up with phone number configuration
To allow sign-up with phone number, pass signUpOnVerification object to phoneNumber plugin configuration with getTempEmail function (required, generates temporary email) and getTempName function (optional, generates temporary name, defaults to using phone number). Additional required user schema fields can be passed in the verify request body.
Sign in with phone number and password endpoint
POST endpoint at /sign-in/phone-number allows sign-in using phone number and password. Parameters: phoneNumber (string, required, example '+1234567890'), password (string, required), rememberMe (boolean, optional, default true). The user must have a corresponding account record with providerId set to 'credential'.
Client method to send OTP for phone number
The client method authClient.phoneNumber.sendOtp({phoneNumber}) sends an OTP to a new phone number for verification or update.
Client method to verify phone number
The client method authClient.phoneNumber.verify({phoneNumber, code, updatePhoneNumber, disableSession}) verifies a phone number with an OTP code. The updatePhoneNumber flag indicates updating existing user's phone number during active session. Additional custom fields can be passed in the verify request.
Update existing user's phone number
To change phone number, first call authClient.phoneNumber.sendOtp with the new phone number, then call authClient.phoneNumber.verify with the new phone number, OTP code, and updatePhoneNumber: true flag. Non-null phone number updates through updateUser are blocked; phone number changes always require OTP verification.
Remove phone number from user account
Logged-in users can remove their phone number by calling authClient.updateUser({phoneNumber: null}). This atomically clears the phone number and resets the verified flag, freeing the number for another account to claim through standard verification flow.
Disable session creation on phone number verification
Pass disableSession: true to authClient.phoneNumber.verify() to prevent automatic session creation after phone number verification. By default, a session is created after successful verification.
Reset password via phone number endpoint
POST endpoint at /phone-number/reset-password resets the password using OTP. Parameters: otp (string, required, example '123456'), phoneNumber (string, required, example '+1234567890'), newPassword (string, required, example 'new-and-secure-password').
Phone number plugin otpLength option
The otpLength option configures the length of generated OTP codes. Default value is 6 characters.
Phone number plugin sendOTP option
The sendOTP option is a required function that receives phoneNumber and code as parameters, plus a context object, and handles sending the OTP code to the user's phone number via SMS. It should not be awaited as this can slow down requests and cause timing attacks.
Phone number plugin expiresIn option
The expiresIn option configures the time in seconds after which an OTP code expires. Default is 300 seconds.
Phone number plugin callbackOnVerification option
The callbackOnVerification option is a function called after phone number verification succeeds. It receives an object with phoneNumber and user properties as first argument and a context object as second argument.
Phone number plugin sendPasswordResetOTP option
The sendPasswordResetOTP option is a function that sends an OTP code to the user's phone number specifically for password reset flows. It takes phoneNumber and code as arguments.
Phone number plugin phoneNumberValidator option
The phoneNumberValidator option is a custom function to validate phone numbers. It takes a phoneNumber string as argument and returns a boolean indicating whether the phone number is valid.
Phone number plugin verifyOTP option for external providers
The verifyOTP option allows using a custom OTP verification function instead of internal verification logic. This is useful when integrating with external SMS providers like Twilio Verify or AWS SNS. The function takes an object with phoneNumber and code properties and a context object, and returns a boolean or promise resolving to a boolean indicating if the OTP is valid.
Phone number plugin signUpOnVerification option
The signUpOnVerification option is an object with getTempEmail (required function) and getTempName (optional function) properties. getTempEmail generates a temporary email from phone number. getTempName generates a temporary name from phone number, defaulting to the phone number itself if not provided.
Phone number plugin requireVerification option
When requireVerification is enabled, users cannot sign in with their phone number until it has been verified. If an unverified user attempts to sign in, the server responds with 401 status (PHONE_NUMBER_NOT_VERIFIED) and automatically sends an OTP to trigger verification.
Phone number user table schema fields
The phone number plugin requires two fields added to the user table: phoneNumber (string, unique, optional) and phoneNumberVerified (boolean, default false, optional). The phoneNumber field stores the user's phone number, and phoneNumberVerified indicates whether it has been verified.
Phone number plugin allowedAttempts option for brute force protection
The allowedAttempts option limits OTP verification attempts to protect against brute force attacks. Default value is 3. When exceeded, the OTP code is automatically deleted and further attempts return 403 (Forbidden) status with 'Too many attempts' message.
Phone number OTP brute force error response
When a user exceeds the allowedAttempts limit, the server responds with status 403 and error message 'Too many attempts'. The user must request a new OTP code to continue.
Phone number plugin does not await sendOTP function
The sendOTP function should not be awaited as this slows down requests and can cause timing attacks. For serverless platforms, use waitUntil to ensure OTP is sent without blocking the request.
Phone number sign-in requires credential account record
To sign in with phone number and password, the user must have a corresponding record in the account table with providerId set to 'credential'. When migrating from another auth provider or seeding users manually, ensure this record exists.
Phone number plugin consumePhoneNumberOTP does not guarantee single-use acceptance
The auth.api.consumePhoneNumberOTP method uses the same validation and consumption behavior as verifyPhoneNumber and does not introduce a stronger concurrency guarantee. If your server flow can receive parallel redemption attempts and requires strict single-use acceptance, configure verifyOTP with a provider that atomically consumes accepted codes.
Phone number consumePhoneNumberOTP security considerations
The consumePhoneNumberOTP method does not return a session or reusable proof of verification. Validate any inputs that do not depend on successful OTP verification first. If exposing this through a public endpoint, apply rate limiting and appropriate abuse protection.
Custom verifyOTP overrides internal verification logic
When using the verifyOTP option with custom verification logic, ensure proper validation is implemented as it completely overrides the internal verification logic.
Phone number plugin database migration required
After adding the phone number plugin to the server configuration, run database migration with 'npx auth migrate' or generate schema with 'npx auth generate' to add the necessary fields and tables to the database.