BETTER-AUTH. UI
Plugins

Phone Number

Add phone verification-code and password sign-in, recovery, and verified phone management.

The HeroUI phone-number plugin contributes a phone sign-in route, password recovery views, and a verified phone-number card for account settings.

Setup

Configure Better Auth and your SMS provider

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

export const auth = betterAuth({
  plugins: [
    phoneNumber({
      otpLength: 6,
      requireVerification: true,
      sendOTP: ({ phoneNumber, code }) => {
        void sms.send({ to: phoneNumber, body: `Your code is ${code}` })
      },
      sendPasswordResetOTP: ({ phoneNumber, code }) => {
        void sms.send({ to: phoneNumber, body: `Your reset code is ${code}` })
      }
    })
  ]
})

Normalize phone numbers on the server, preferably to E.164. Do not log codes in production. Better Auth recommends dispatching the SMS without waiting for the provider response.

Update the schema

Use your normal Better Auth schema generation or migration flow. The user model needs nullable phoneNumber and phoneNumberVerified fields, with phoneNumber kept unique.

Add the client plugin

lib/auth-client.ts
import { createAuthClient } from "better-auth/react"
import { phoneNumberClient } from "better-auth/client/plugins"

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

Register the HeroUI plugin

components/providers.tsx
import { AuthProvider } from "@better-auth-ui/heroui"
import { phoneNumberPlugin } from "@better-auth-ui/heroui/plugins"

<AuthProvider
  authClient={authClient}
  navigate={navigate}
  plugins={[
    phoneNumberPlugin({
      signIn: true,
      passwordSignIn: true,
      passwordReset: true,
      changePhoneNumber: true
    })
  ]}
>
  {children}
</AuthProvider>

Allow the new route segments

import { viewPaths } from "@better-auth-ui/core"
import { phoneNumberPlugin } from "@better-auth-ui/heroui/plugins"

const validAuthPaths = new Set([
  ...Object.values(viewPaths.auth),
  ...Object.values(phoneNumberPlugin().viewPaths.auth)
])

Flow options

UI optionDefaultServer requirement
signIntruesendOTP
passwordSignInfalseA password credential
passwordResetfalsesendPasswordResetOTP
changePhoneNumbertruesendOTP
otpLength6Must match Better Auth otpLength

When password sign-in reports PHONE_NUMBER_NOT_VERIFIED, the UI switches to the code step. Better Auth sends that verification code automatically.

Passwordless phone verification is not a second factor. Better Auth applies 2FA to phone number and password sign-in, but not to passwordless verification.

Enable Better Auth signUpOnVerification if an unknown verified number may create an account. Use a custom phone-number view if verification must also submit other required user fields.

Options and localization

Prop

Type

Prop

Type

The implementation uses the React phone-number mutations. See the Better Auth phone-number plugin for all server options.

Last updated on

On this page