Skip to main content
The phoneAuth plugin registers and authenticates users with a phone number and a one-time code. You supply the SMS delivery function. KavachOS handles code generation, expiry, and rate limiting.

Setup

lib/kavach.ts
import { createKavach } from 'kavachos';
import { phoneAuth } from 'kavachos/auth'; 
import { Twilio } from 'twilio';

const twilio = new Twilio(process.env.TWILIO_SID!, process.env.TWILIO_TOKEN!);

const kavach = await createKavach({
  database: { provider: 'postgres', url: process.env.DATABASE_URL! },
  secret: process.env.KAVACH_SECRET!,
  baseUrl: 'https://auth.example.com',
  plugins: [
    phoneAuth({ 
      onSendCode: async (phone, code) => { 
        await twilio.messages.create({ 
          body: `Your verification code: ${code}`, 
          from: process.env.TWILIO_FROM!, 
          to: phone, 
        }); 
      }, 
      codeLength: 6, 
      codeExpiry: 300, // seconds
    }), 
  ],
});
Mount the handler the same way as any other plugin, see adapters.

Send code

POST /auth/phone/send-code Sends a one-time code to the given phone number. Creates the user account on first send.
Send code (client)
const res = await fetch('/auth/phone/send-code', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    phone: '+14155550123', // E.164 format
  }),
});

// Always returns { success: true } to prevent phone enumeration
Phone numbers must be in E.164 format (+ prefix, country code, number). Error codes
CodeStatusMeaning
PHONE_INVALID422Not a valid E.164 phone number
RATE_LIMITED429Too many codes sent to this number

Verify code

POST /auth/phone/verify-code Submits the code the user received. Returns a session on success.
Verify code (client)
const res = await fetch('/auth/phone/verify-code', {
  method: 'POST',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    phone: '+14155550123', 
    code: '482910', 
  }),
});

if (res.ok) {
  const { user, session } = await res.json();
}
Error codes
CodeStatusMeaning
INVALID_CODE401Code is wrong or expired
CODE_EXPIRED401Code was valid but has passed its expiry window

Configuration reference

onSendCode
required
Callback invoked to deliver the code. Receives the phone number (E.164) and the numeric code as a string.
codeLength
number
default:6
Number of digits in the generated code.
codeExpiry
number
default:"300 (5 min)"
Code validity window in seconds.
maxAttempts
number
default:5
Failed attempts allowed before the code is invalidated.
Last modified on April 18, 2026