---
title: Phone Number
description: Phone number plugin
---

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

<Steps>
    <Step>
        ### Add Plugin to the server

        ```ts title="auth.ts"
        import { betterAuth } from "better-auth"
        import { phoneNumber } from "better-auth/plugins"

        const auth = betterAuth({
            plugins: [ 
                phoneNumber({  // [!code highlight]
                    sendOTP: ({ phoneNumber, code }, ctx) => { // [!code highlight]
                        // Implement sending OTP code via SMS // [!code highlight]
                    } // [!code highlight]
                }) // [!code highlight]
            ] 
        })
        ```
    </Step>
    <Step>
        ### Migrate the database

        Run the migration or generate the schema to add the necessary fields and tables to the database.

        <Tabs items={["migrate", "generate"]}>
            <Tab value="migrate">
            ```package-install
            npx @better-auth/cli migrate
            ```
            </Tab>
            <Tab value="generate">
            ```package-install
            npx @better-auth/cli generate
            ```
            </Tab>
        </Tabs>
        See the [Schema](#schema) section to add the fields manually.
    </Step>
    <Step>
        ### Add the client plugin

        ```ts title="auth-client.ts"
        import { createAuthClient } from "better-auth/client"
        import { phoneNumberClient } from "better-auth/client/plugins"

        const authClient = createAuthClient({
            plugins: [ // [!code highlight]
                phoneNumberClient() // [!code highlight]
            ] // [!code highlight]
        })
        ```
    </Step>
</Steps>

## Usage

### Send OTP for Verification

To send an OTP to a user's phone number for verification, you can use the `sendVerificationCode` endpoint.

<APIMethod path="/phone-number/send-otp" method="POST">
```ts
type sendPhoneNumberOTP = {
    /**
     * Phone number to send OTP. 
     */
    phoneNumber: string = "+1234567890"
}
```
</APIMethod>

### Verify Phone Number

After the OTP is sent, users can verify their phone number by providing the code.

<APIMethod path="/phone-number/verify" method="POST">
```ts
type verifyPhoneNumber = {
    /**
     * Phone number to verify.
     */
    phoneNumber: string = "+1234567890"
    /**
     * OTP code.
     */
    code: string = "123456"
    /**
     * Disable session creation after verification.
     */
    disableSession?: boolean = false
    /**
     * Update the phone number of an existing logged-in user.
     * Requires an active session.
     */
    updatePhoneNumber?: boolean = false
}
```
</APIMethod>

### Allow Sign-Up with Phone Number

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.

```ts title="auth.ts"
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
                }
            }
        })
    ]
})
```

<Callout>
We highly recommend not awaiting the `sendOTP` function. If you await it, it'll slow down the request and could cause timing attacks. For serverless platforms, you can use `waitUntil` to ensure the OTP is sent.
</Callout>

If you have additional required fields in your user schema, you can pass them in the verify request body:

```ts title="auth-client.ts"
await authClient.phoneNumber.verify({
    phoneNumber: "+1234567890",
    code: "123456",
    customField: "custom-value", // additional field [!code highlight]
})
```

### 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.

<APIMethod path="/sign-in/phone-number" method="POST">
```ts
type signInPhoneNumber = {
    /**
     * Phone number to sign in. 
     */
    phoneNumber: string = "+1234567890"
    /**
     * Password to use for sign in. 
     */
    password: string
    /**
     * Remember the session. 
     */
    rememberMe?: boolean = true
}
```
</APIMethod>

### Update Phone Number

Already logged-in users can change their phone number to a new one. First, send an OTP to the new phone number:

```ts title="auth-client.ts"
await authClient.phoneNumber.sendOtp({
    phoneNumber: "+1234567890" // New phone number
})
```

Then verify the new phone number with `updatePhoneNumber: true`:

```ts title="auth-client.ts"
const isVerified = await authClient.phoneNumber.verify({
    phoneNumber: "+1234567890",
    code: "123456",
    updatePhoneNumber: true // [!code highlight]
})
```

### Disable Session Creation

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.

```ts title="auth-client.ts"
const isVerified = await authClient.phoneNumber.verify({
    phoneNumber: "+1234567890",
    code: "123456",
    disableSession: true // [!code highlight]
})
```

### Request Password Reset

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.

<APIMethod path="/phone-number/request-password-reset" method="POST">
```ts
type requestPasswordResetPhoneNumber = {
    /**
     * The phone number which is associated with the user. 
     */
    phoneNumber: string = "+1234567890"
}
```
</APIMethod>

Then, you can reset the password by calling `resetPassword` on the client with the OTP code and the new password.

<APIMethod path="/phone-number/reset-password" method="POST">
```ts
type resetPasswordPhoneNumber = {
    /**
     * The one time password to reset the password. 
     */
    otp: string = "123456"
    /**
     * The phone number to the account which intends to reset the password for. 
     */
    phoneNumber: string = "+1234567890"
    /**
     * The new password. 
     */
    newPassword: string = "new-and-secure-password"
}
```
</APIMethod>

## Options

### `otpLength`

The length of the OTP code to be generated. Default is `6`.

### `sendOTP`

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`

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.

```ts
export const auth = betterAuth({
    plugins: [
        phoneNumber({
            sendOTP: ({ phoneNumber, code }, ctx) => {
                // Implement sending OTP code via SMS
            },
            callbackOnVerification: async ({ phoneNumber, user }, ctx) => { // [!code highlight]
                // Implement callback after phone number verification // [!code highlight]
            } // [!code highlight]
        })
    ]
})
```

### `sendPasswordResetOTP`

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`

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.

```ts
export const auth = betterAuth({
    plugins: [
        phoneNumber({
            sendOTP: ({ phoneNumber, code }, ctx) => {
                // Send OTP via your SMS provider
            },
            verifyOTP: async ({ phoneNumber, code }, ctx) => { // [!code highlight]
                // Verify OTP with your desired logic (e.g., Twilio Verify) // [!code highlight]
                // This is just an example, not a real implementation. // [!code highlight]
                const isValid = await twilioClient.verify // [!code highlight]
                    .services('YOUR_SERVICE_SID') // [!code highlight]
                    .verificationChecks // [!code highlight]
                    .create({ to: phoneNumber, code }); // [!code highlight]
                return isValid.status === 'approved'; // [!code highlight]
            } // [!code highlight]
        })
    ]
})
```

<Callout type="warn">
When using this option, ensure that proper validation is implemented, as it overrides our internal verification logic.
</Callout>

### `signUpOnVerification`

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`

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
<DatabaseTable
    fields={[
        { 
            name: "phoneNumber", 
            type: "string", 
            description: "The phone number of the user",
            isUnique: true,
            isOptional: true
        },
        { 
            name: "phoneNumberVerified", 
            type: "boolean", 
            description: "Whether the phone number is verified or not",
            defaultValue: false,
            isOptional: true
        },
    ]}
    />

### OTP Verification Attempts

The phone number plugin includes a built-in protection against brute force attacks by limiting the number of verification attempts for each OTP code.

```typescript
phoneNumber({
  allowedAttempts: 3, // default is 3
  // ... other options
})
```

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:
```json
{
  "error": {
    "status": 403,
    "message": "Too many attempts"
  }
}
```

<Callout type="warning">
When receiving a 403 status, prompt the user to request a new OTP code
</Callout>
