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 Numbers → Manage → Buy 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 Console → Authentication → SMS 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 withMG)
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
/api/user/phone/send-otpSend 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.
/api/user/phone/verify-otpVerify 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:
React
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:
/api/user/2fa/sms/sendSend an SMS OTP to the authenticated user’s verified phone number. Requires a partial session token issued after first-factor authentication.
/api/auth/verify-2faSubmit 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.
/api/user/phoneSet or update the authenticated user’s phone number. Accepts E.164 format (e.g., +15551234567). Sends a verification OTP immediately.
/api/user/phone/verifyVerify the OTP sent to the new phone number. Body: { code: string }. Marks the phone number as verified.
/api/user/phoneRemove 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:
| Limit | Value |
|---|---|
| OTP requests per phone per hour | 5 |
| Cooldown between sends | 30 seconds |
| Maximum verification attempts per code | 5 |
| Code validity | 10 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.
Related Guides
- Passkeys / WebAuthn — Stronger 2FA using biometrics and hardware keys
- Magic Links — Email-based passwordless authentication
- Hosted Login (PKCE) — The full authentication flow used in production