Multi-Factor Authentication (MFA)

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:

PolicyBehavior
optionalUsers can choose to enable MFA
encouragedPrompt users to enable MFA (but don’t block)
requiredAll 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.