AuthFI supports TOTP-based MFA with backup codes. MFA can be enforced per-tenant, per-organization, or per-access-policy.
TOTP enrollment
1 · Enroll
POST /v1/acme/mfa/enroll
Authorization: Bearer <access_token> Response:
{
"factor_id": "factor-uuid",
"type": "totp",
"secret": "JBSWY3DPEHPK3PXP",
"uri": "otpauth://totp/AuthFI:alice@acme.com?secret=JBSWY3DPEHPK3PXP&issuer=AuthFI",
"qr_code": "data:image/png;base64,..."
} Display the QR code for the user to scan with Google Authenticator, Authy, or 1Password.
2 · Verify
POST /v1/acme/mfa/verify
Authorization: Bearer <access_token>
{ "code": "123456" } On successful verification, AuthFI generates 10 backup codes returned in the response. These are shown once and should be saved by the user.
{
"verified": true,
"backup_codes": [
"a1b2c3d4", "e5f6g7h8", "i9j0k1l2", "m3n4o5p6", "q7r8s9t0",
"u1v2w3x4", "y5z6a7b8", "c9d0e1f2", "g3h4i5j6", "k7l8m9n0"
]
} 3 · Login with MFA
When a user with MFA logs in:
POST /v1/acme/auth/login
{ "email": "alice@acme.com", "password": "..." }
# Response (MFA required):
{ "mfa_required": true, "mfa_token": "temp-token" }
# Second request with TOTP code:
POST /v1/acme/auth/login
{ "email": "alice@acme.com", "password": "...", "mfa_code": "123456" }
# Or with backup code:
{ "email": "alice@acme.com", "password": "...", "mfa_code": "a1b2c3d4" } MFA Policy
Configure MFA requirements at the tenant or organization level:
optional
Users can choose to enable MFA. Default for new tenants.
encouraged
Prompt users to enable MFA. Doesn't block login if disabled.
required
All users must have MFA enabled to log in.
PATCH /manage/v1/acme/tenant
{ "mfa_policy": "required" } MFA in access policies
eBPF and AuthFI Connect policies can require MFA:
{
"method": "POST",
"path_pattern": "/api/admin/*",
"required_roles": ["admin"],
"require_mfa": true
} The JWT contains "mfa_verified": true when the user’s session includes a verified MFA challenge.
List factors
GET /v1/acme/mfa/factors
Authorization: Bearer <access_token> Returns enrolled factors (type, verified status). Secrets are never returned.
Unenroll
POST /v1/acme/mfa/unenroll
Authorization: Bearer <access_token>
{ "factor_id": "factor-uuid", "code": "123456" } Requires a valid TOTP code to confirm unenrollment — prevents unauthorized removal.