Skip to main content

SMS code (OTP) authentication

Not yet available (2.4.x)

The SMS (OTP) provider is not enabled yet. Only Google is live right now — calling auth.signIn() with this provider throws AuthErrorCode.PROVIDER_NOT_ENABLED. The page below documents its intended shape for when it is re-enabled. See the provider overview and the Google provider.

The SMS provider is a passwordless, two-step flow: the first call asks your backend to text a one-time code to a phone number, and the second call submits that code for verification. The library tracks the pending verification (metadata only, persisted across reloads) and orchestrates state; your backend integrates with an SMS service (Twilio, AWS SNS, etc.) to send and validate the code.

Backend requirement

This provider needs a backend. The web implementation (src/providers/web/sms-provider.ts) POSTs { phoneNumber, clientId, codeLength } to your send-code endpoint and expects a sessionId back, then POSTs { phoneNumber, code, sessionId, clientId } to your verify endpoint and expects a user (uid, optional tokens). A 401 on verify becomes INVALID_CODE. The code is never stored client-side — only non-secret metadata (session id, expiry, attempt count) is persisted.

The web provider reads its endpoint URLs from runtime options — sendCodeUrl and verifyCodeUrl (required), plus optional clientId, countryCode, codeLength, resendDelay. This runtime config differs from the typed SmsAuthOptions interface documented below — supply sendCodeUrl and verifyCodeUrl so the provider can reach your backend.

Configuration

import { auth } from 'capacitor-auth-manager';

auth.configure({
providers: {
sms: {
provider: 'twilio',
twilioConfig: {
accountSid: 'YOUR_SID',
authToken: 'YOUR_TOKEN',
fromNumber: '+1234567890',
},
codeLength: 6,
},
},
});

Options

From the SmsAuthOptions interface in src/definitions.ts:

OptionTypeRequiredPurpose
provider'twilio' | 'firebase' | 'custom'YesWhich SMS backend strategy to use.
twilioConfig{ accountSid; authToken; fromNumber }NoTwilio credentials (keep secrets server-side).
firebaseConfig{ apiKey; projectId }NoFirebase phone-auth config.
customConfig{ endpoint; apiKey?; headers? }NoCustom send/verify endpoint config.
codeLengthnumberNoNumber of digits in the code.
codeExpirationnumberNoCode lifetime in milliseconds.
maxAttemptsnumberNoAllowed verification attempts.
testModebooleanNoUse test phone numbers instead of real sends.
testPhoneNumbersRecord<string, string>NoPhone-number-to-code map for test mode.

Sign in

The flow is two calls with SmsCodeCredentials ({ phoneNumber, code? }):

// Step 1 — request the code (no `code`)
await auth.signIn({ provider: 'sms', credentials: { phoneNumber: '+1234567890' } });

// Step 2 — verify the code
await auth.signIn({
provider: 'sms',
credentials: { phoneNumber: '+1234567890', code: '123456' },
});

Errors

All failures are thrown as AuthError with an AuthErrorCode:

  • PHONE_REQUIRED — phone number missing.
  • INVALID_CODE / CODE_EXPIRED — verification failed or the code lapsed.
  • NO_PENDING_VERIFICATION — verifying without a sent code.
  • TOO_MANY_ATTEMPTS / RESEND_DELAY — attempt or resend throttling.