Skip to content

SMS fallback

SMS-based one-time codes are the most familiar form of MFA — the user gets a six-digit code by text, types it in, and they're through. Adoption is high because no setup is required beyond a phone number. The security trade-off is real: SS7 weaknesses and SIM-swap attacks have been used in the wild to redirect SMS codes.

The recommendation is firm: use SMS as a fallback for users who cannot use WebAuthn or TOTP, not as a primary MFA option. NIST 800-63B has flagged SMS as a restricted authenticator since its 2017 revision, with later drafts (SP 800-63-4) keeping the same posture.

That said, fallback matters. A user locked out of TOTP needs some way back in, and an SMS-friendly account recovery path is often part of that.

const { startMfaEnrolment } = useIntelliAuth()
const enrolment = await startMfaEnrolment('sms', {
phone_number: '+14155550100', // E.164 format, always
})
// enrolment.kind === 'pending' — the user receives an SMS with a code

E.164 format (+<country-code><number>, no spaces, no dashes) is required. The platform refuses other formats. Most JS phone-input libraries normalise to E.164 for you; use one.

The user reads the code from their SMS and types it back:

const result = await enrolment.complete({ code: '123456' })

On success, the factor is enrolled.

const { initiateMfaStep, completeMfaStep } = useIntelliAuth()
await initiateMfaStep(flowId, 'sms') // triggers the SMS send
const result = await completeMfaStep(flowId, 'sms', { code: '654321' })

Splitting initiation from completion lets you show "Sending code..." UI while the SMS is on its way.

SMS costs money and can be abused. The platform enforces:

  • Per-user enrolment rate — a user can request at most N enrolment SMS messages per hour. Configurable in the tenant admin console, default 5.
  • Per-user authentication rate — at most N codes per hour for the same authentication flow. Default 3.
  • Per-IP rate — same caller cannot trigger more than N sends per hour across all users. Defends against attackers walking phone numbers.
  • Failed-code lockout — entering the wrong code N times in a row burns the current code and triggers a brief lockout. Default: 5 attempts, 15 minutes lockout.

When a limit is hit, the next request returns an error indicating "rate limited"; the SDK surfaces this so your UI can tell the user to wait.

The tenant admin console supports per-country send rules:

  • Allow-list — only send to specific countries.
  • Block-list — refuse specific countries.
  • Cost cap — block sends to high-cost destinations after a daily threshold.

Configure these if your user base is geographically known. The defaults are permissive; tighten them once you're live.

Phone numbers are PII. The platform stores them encrypted at rest. They are visible in the user profile to administrators and to the user themselves. They do not appear in audit logs as plaintext (only the last 4 digits, for incident attribution).

If you display the user's phone number in your UI — for example, in account settings, "the number we'll text" — mask all but the last 4. Show the full number only inside an explicit reveal action.

Common failure modes and the right user-facing copy:

SymptomCauseWhat to tell the user
No SMS received within 30 secondsCarrier delay, wrong country, network filter"Didn't get a code? Wait another minute, then click resend."
Code received but rejectedWrong code, expired (5 minute TTL), or already used"Make sure you typed the latest code. Codes expire after 5 minutes."
Resend rate-limitedThe user is clicking resend too aggressively"Codes are limited to a few per hour. Wait 10 minutes, then try again."

The audit log records every SMS-MFA event with the specific failure code on the platform side.

For users who lose access to their primary MFA (lost phone, broken authenticator app), SMS to a verified backup phone is the most common recovery path. Configure the tenant's recovery policy to allow this, but treat it as a sensitive flow:

  • Require the user to re-prove identity (password + security questions, for example) before sending the SMS.
  • Notify the user via email when a recovery SMS is sent.
  • Surface the recovery event prominently in the audit log; it is a frequent target of social-engineering attacks against support teams.

Your tenant's MFA recovery runbook in the tenant admin console covers the full workflow.