Multi-factor authentication
Let app users protect their account with an authenticator app or SMS codes and one-time backup codes: enrolment, signing in with a second factor, recovery, lockouts and turning it off.
With MFA on, signing in needs a password (or link, or provider) and a code from something the user has. Sovaria supports authenticator apps (TOTP — Google Authenticator, 1Password, Authy…), SMS codes and backup codes. MFA for app users is available on every plan; hardware security keys are listed in Plan limits.
| Free | Pro | Ultra | Team | Enterprise | |
|---|---|---|---|---|---|
| Multi-factor authentication for app users | ✓ | ✓ | ✓ | ✓ | ✓ |
| Hardware-key MFA | — | — | — | — | ✓ |
Turn on an authenticator app
Start enrolment
For the signed-in user,
enrollreturns a secret, anotpauth://URI to show as a QR code, and backup codes.const { totp_uri, secret, backup_codes } = await sovaria.auth.mfa.enroll() showQrCode(totp_uri) // or let the user type `secret` showOnce(backup_codes) // they are never shown againConfirm with a code
The user enters the 6-digit code from their app.
await sovaria.auth.verifyMfa(code)Done
sovaria.auth.mfa.status()now reports MFA on. Future sign-ins ask for a code.
Sign in with a second factor
const result = await sovaria.auth.signIn(email, password)
if (result.mfa_required) {
const code = await askForCode() // authenticator, SMS or a backup code
await sovaria.auth.verifyMfa(code) // 'totp' (default) or verifyMfa(code, 'phone')
}
// signed in, with a two-factor (aal2) sessionAfter the password step the client holds only a short challenge token; nothing else works until the code is verified. A verified session is marked aal2 in its token (auth.jwt() ->> 'aal'), so you can require it for sensitive actions.
SMS codes
Users can add a phone number as a factor (POST /api/v1/auth/mfa/phone/enroll, then verify-enrollment with the code they receive). At sign-in, POST /api/v1/auth/mfa/phone/challenge sends a code and verifyMfa(code, 'phone') checks it. Codes are rate-limited per user to stop abuse and SMS costs.
Backup codes and recovery
- Each backup code works once, in place of an authenticator code. Show them only at enrolment; Sovaria stores only hashes.
GET /api/v1/auth/mfa/backup-codesreports how many are left;POST /api/v1/auth/mfa/backup-codes/regenerateissues a new set (the old set stops working).- A user who lost their phone and codes can't pass MFA. Your team can reset MFA for them from the Users page after checking who they are.
Built-in protection
- Lockout: 5 wrong codes within 5 minutes lock the factor for a while (
423withRetry-After) — per user, so rotating IPs doesn't help an attacker. - No replay: a code that was accepted can't be used again (
401 CODE_ALREADY_USED). - Turning MFA off needs a current code:
sovaria.auth.mfa.disable(code).
Project settings
Under Authentication › Multi-factor choose which second factors your users can add.