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.
Two scopes
Section titled “Two scopes”MFA in Mittr operates at two levels:
| Scope | Where it’s set | What it controls |
|---|---|---|
| Per-user | Settings → Security → “Your MFA” | Whether this user presents a TOTP at every login |
| Per-workspace | Settings → 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.
Enroll a user
Section titled “Enroll a user”- Open Settings → Security.
- Click Set up authenticator app in the “Your MFA” card.
- Scan the QR code with your authenticator app, or copy the secret if you’d rather type it manually.
- Type the 6-digit code your app shows back into Mittr to confirm the secret was saved correctly.
- 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.
Enforce MFA workspace-wide
Section titled “Enforce MFA workspace-wide”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
Section titled “Backup codes”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):
- Settings → Security → “Your MFA” → Regenerate codes.
- 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.”
Disable per-user MFA
Section titled “Disable per-user MFA”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.
How it interacts with SSO
Section titled “How it interacts with SSO”| User logs in via | MFA 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 key | N/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.
Operator notes
Section titled “Operator notes”ENCRYPTION_KEYmust be set on the server for MFA to be available. The TOTP secret is encrypted at rest with this key. IfENCRYPTION_KEYis unset, the MFA endpoints returnNOT_IMPLEMENTEDand the dashboard hides the panel.mfa_requiredlives on theclientsrow. SQL operators can flip it directly if the dashboard is unavailable, but prefer the API:PATCH /api/v1/me/mfa-requiredwith{"required": true}.- Every MFA enroll, verify, and disable event lands in
auth_audit_logs— see the Compliance guide for how to read the trail.
API reference
Section titled “API reference”GET /auth/mfa/status— current user’s enrollment + verification statePOST /auth/mfa/enroll— start enrollment, returns secret + provisioning URIPOST /auth/mfa/verify-enrollment— confirm with first TOTP, returns backup codesPOST /auth/mfa/verify— challenge step at login (setsmfa_verified)POST /auth/mfa/verify-backup— same shape, accepts a backup codePOST /auth/mfa/disable— turn off, requires fresh TOTP or backupPOST /auth/mfa/backup-codes/regenerate— mint a new batchPATCH /api/v1/me/mfa-required— admin-only, toggle the workspace gate