Skip to Content
GuidesAuthenticationSMS OTP

SMS OTP

Auris supports SMS one-time passwords (OTP) in two modes:

  • Passwordless: The user enters their phone number, receives an SMS code, and authenticates without a password
  • Two-factor authentication (2FA): The user completes password login, then receives an SMS code as a second factor

Both modes use the same underlying mechanism — a short-lived numeric code delivered via Twilio. The mode is determined by how the flow is initiated.


Twilio Setup

Auris uses Twilio as the SMS provider. You must have a Twilio account with a phone number or messaging service.

Create a Twilio account

If you do not have one, sign up at twilio.com . Complete phone number verification.

Obtain credentials

From the Twilio Console dashboard, note your Account SID and Auth Token.

Get a Twilio phone number

Under Phone NumbersManageBuy a number, purchase a number with SMS capability. Alternatively, create a Messaging Service for better deliverability and sender pool management.

Configure in Auris Console

Go to ConsoleAuthenticationSMS and enter:

  • Account SID — from Twilio dashboard
  • Auth Token — from Twilio dashboard
  • Sender — your Twilio phone number (E.164 format, e.g., +15551234567) or your Messaging Service SID (starts with MG)

Save and test

Click Save, then use the Send Test SMS button to verify the configuration with your own phone number.

OTP codes are 6-digit numeric codes valid for 10 minutes. The code format and expiry are not configurable in the current release.


SMS as Passwordless Login

In this mode, the user authenticates using only their phone number and the OTP code — no password is required.

Prerequisites

  • The user’s phone number must already be registered and verified on their account. Phone numbers cannot be collected as part of a passwordless-first flow.
  • SMS passwordless must be enabled in Console → Authentication → Passwordless → SMS OTP.

Flow

User enters phone number

Your application collects the user’s phone number (E.164 format) and calls the send OTP endpoint.

OTP is sent

Auris generates a 6-digit code, stores its SHA-256 hash, and sends it via Twilio.

User enters the code

Your application presents an input for the 6-digit code and submits it to the verify endpoint.

Authentication is complete

Auris validates the code and issues an access token and refresh token.

API Usage

POST/api/user/phone/send-otp

Send an OTP to the specified phone number for passwordless authentication. Body: { phone: string } (E.164 format). Rate limited: 5 codes per hour, 30-second cooldown.

POST/api/user/phone/verify-otp

Verify the OTP and issue tokens. Body: { phone: string, code: string }. Maximum 5 verification attempts per code.


SMS as Two-Factor Authentication (2FA)

In this mode, SMS OTP is a second factor. The user first completes email/password (or social) authentication, and if 2FA is required, Auris delivers an SMS code before issuing tokens.

Enabling SMS 2FA

Per user (self-service): The user enables SMS 2FA from their account security settings:

import { useAuris } from '@auris/react' function SmsTwoFactorSetup() { const { getAccessToken } = useAuris() const [step, setStep] = useState('phone') // 'phone' | 'verify' | 'done' const [phone, setPhone] = useState('') const [code, setCode] = useState('') async function setPhone() { const token = await getAccessToken() await fetch('/api/user/phone', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ phoneNumber: phone }), }) setStep('verify') } async function verifyAndEnable() { const token = await getAccessToken() await fetch('/api/user/phone/verify', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ code }), }) await fetch('/api/user/2fa/sms', { method: 'POST', headers: { Authorization: `Bearer ${token}` }, }) setStep('done') } if (step === 'phone') { return ( <form onSubmit={(e) => { e.preventDefault(); setPhone() }}> <input type="tel" placeholder="+15551234567" value={phone} onChange={(e) => setPhone(e.target.value)} /> <button type="submit">Send verification code</button> </form> ) } if (step === 'verify') { return ( <form onSubmit={(e) => { e.preventDefault(); verifyAndEnable() }}> <input placeholder="6-digit code" value={code} onChange={(e) => setCode(e.target.value)} maxLength={6} /> <button type="submit">Verify and enable SMS 2FA</button> </form> ) } return <p>SMS two-factor authentication is now enabled.</p> }

The 2FA Login Flow

During a login where SMS 2FA is required, the hosted login page handles the second factor automatically. If you are implementing a custom login UI using the API directly:

POST/api/user/2fa/sms/send

Send an SMS OTP to the authenticated user’s verified phone number. Requires a partial session token issued after first-factor authentication.

POST/api/auth/verify-2fa

Submit the 2FA code. Body: { code: string, method: 'sms' }. On success, issues full access and refresh tokens.


Phone Number Management

Users manage their phone number through account settings. The phone must be verified via OTP before it can be used for authentication.

POST/api/user/phone

Set or update the authenticated user’s phone number. Accepts E.164 format (e.g., +15551234567). Sends a verification OTP immediately.

POST/api/user/phone/verify

Verify the OTP sent to the new phone number. Body: { code: string }. Marks the phone number as verified.

DELETE/api/user/phone

Remove the phone number from the authenticated user’s account. Automatically disables SMS 2FA if enabled.


Rate Limits

Auris enforces strict rate limits on SMS endpoints to prevent abuse and control Twilio costs:

LimitValue
OTP requests per phone per hour5
Cooldown between sends30 seconds
Maximum verification attempts per code5
Code validity10 minutes

After 5 failed verification attempts, the code is invalidated. The user must request a new code.

After the hourly limit is reached, the endpoint returns a 429 Too Many Requests response with a Retry-After header indicating when the limit resets.


Security Considerations

E.164 validation — Phone numbers are validated against E.164 format on input. Invalid formats are rejected before any SMS is sent.

Phone ownership verification — Auris requires OTP verification before marking a phone number as verified. A phone number cannot be used for authentication until it has been verified.

Code hashing — OTP codes are stored as SHA-256 hashes. The raw code is only present in the SMS message — never in the Auris database.

SIM swap risk — SMS OTP is less resistant to SIM swap attacks than TOTP or WebAuthn. For applications with high-value accounts, consider using Passkeys / WebAuthn or TOTP as the 2FA method.

SMS authentication is vulnerable to SIM swap and SS7 interception attacks. For accounts requiring strong security guarantees, WebAuthn passkeys or hardware security keys are recommended as the 2FA method.