Skip to content
mittr

Multi-Factor Authentication

Multi-factor authentication (MFA) adds a second factor to Mittr logins so a leaked password isn’t enough to take over a workspace. Mittr implements TOTP (time-based one-time passwords, RFC 6238) — any authenticator app that scans a QR code works: 1Password, Authy, Google Authenticator, Microsoft Authenticator, and so on.

MFA in Mittr operates at two levels:

ScopeWhere it’s setWhat it controls
Per-userSettings → Security → “Your MFA”Whether this user presents a TOTP at every login
Per-workspaceSettings → Security → “Workspace MFA”Whether every non-SSO user on the tenant must have MFA enrolled

Per-user enrollment is voluntary by default. Flipping the workspace toggle on forces every non-SSO user to enroll on their next login; SSO users skip the gate because their identity provider is the authentication authority.

  1. Open Settings → Security.
  2. Click Set up authenticator app in the “Your MFA” card.
  3. Scan the QR code with your authenticator app, or copy the secret if you’d rather type it manually.
  4. Type the 6-digit code your app shows back into Mittr to confirm the secret was saved correctly.
  5. Save the 10 backup codes that appear. You see them exactly once; each one works as a one-shot replacement for a TOTP code if you lose your phone.

After enrollment, the next login (and every subsequent login) shows an MFA challenge after your password.

Workspace admins can toggle the “Require MFA for this workspace” switch in Settings → Security. With it on:

  • Every non-SSO user without MFA enrolled is redirected to the enrollment screen on their next login. They can’t reach /api/v1/* until they finish.
  • SSO users are unaffected — their IdP handles MFA. (If your IdP doesn’t enforce MFA, fix that there, not here.)
  • API key auth is unaffected. API keys are independent authentication primitives with their own scopes; you rotate them when you suspect compromise.

The toggle never retroactively invalidates existing sessions — users stay signed in until their next reauth, then hit the gate.

Backup codes are the recovery path for “I lost my phone.” Each code works exactly once and is one-way hashed in the database (the plaintext shows once at enrollment).

To regenerate codes (e.g. after using them all, or after suspecting compromise):

  1. Settings → Security → “Your MFA” → Regenerate codes.
  2. Re-authenticate with a current TOTP. Old codes are invalidated; new codes are shown once.

If you’ve lost both the authenticator app and the backup codes, ask a workspace admin to remove your user from the team and re-invite you. There’s no operator backdoor — the design is “your MFA secret never leaves your phone or our database in plaintext.”

Settings → Security → “Your MFA” → Disable. Requires a current TOTP or backup code to confirm — a hijacked session can’t silently unwind the second factor.

If the workspace MFA toggle is on, disabling per-user MFA bounces you back to the enrollment screen on next login. The two settings compose: the workspace gate sets the floor, the user setting controls the current state.

User logs in viaMFA at our gate?
Password (no MFA enrolled, workspace MFA off)
Password (MFA enrolled, workspace MFA off)
Password (workspace MFA on)✅ — forced enrollment if missing
SAML / OIDC❌ at our gate (the IdP handles it)
API keyN/A — API keys are not session-authed

The mfa_verified bit on a session is true after a successful TOTP challenge or for any SSO-issued session. The middleware that gates /api/v1/* reads this bit when the workspace toggle is on.

  • ENCRYPTION_KEY must be set on the server for MFA to be available. The TOTP secret is encrypted at rest with this key. If ENCRYPTION_KEY is unset, the MFA endpoints return NOT_IMPLEMENTED and the dashboard hides the panel.
  • mfa_required lives on the clients row. SQL operators can flip it directly if the dashboard is unavailable, but prefer the API: PATCH /api/v1/me/mfa-required with {"required": true}.
  • Every MFA enroll, verify, and disable event lands in auth_audit_logs — see the Compliance guide for how to read the trail.
  • GET /auth/mfa/status — current user’s enrollment + verification state
  • POST /auth/mfa/enroll — start enrollment, returns secret + provisioning URI
  • POST /auth/mfa/verify-enrollment — confirm with first TOTP, returns backup codes
  • POST /auth/mfa/verify — challenge step at login (sets mfa_verified)
  • POST /auth/mfa/verify-backup — same shape, accepts a backup code
  • POST /auth/mfa/disable — turn off, requires fresh TOTP or backup
  • POST /auth/mfa/backup-codes/regenerate — mint a new batch
  • PATCH /api/v1/me/mfa-required — admin-only, toggle the workspace gate