--- # nuzlocke-tracker-f2hs title: Optional TOTP MFA for email/password accounts status: in-progress type: feature priority: normal created_at: 2026-03-21T12:19:18Z updated_at: 2026-03-21T12:56:34Z parent: nuzlocke-tracker-wwnu --- ## Problem Users who sign up with email/password have no MFA option. Google/Discord OAuth users get their provider's MFA, but email-only users have a weaker security posture. ## Approach Supabase has built-in TOTP MFA support via the `supabase.auth.mfa` API. This should be optional — users can enable it from their profile/settings page. ### Backend - No backend changes needed — Supabase handles MFA enrollment and verification at the auth layer - JWT tokens from MFA-enrolled users include an `aal` (authenticator assurance level) claim; optionally validate `aal2` for sensitive operations in the future ### Frontend 1. Add MFA setup flow to user profile/settings page: - "Enable MFA" button → calls `supabase.auth.mfa.enroll({ factorType: 'totp' })` - Show QR code from enrollment response - Verify with TOTP code → `supabase.auth.mfa.challengeAndVerify()` 2. Add MFA challenge during login: - After email/password sign-in, check `supabase.auth.mfa.getAuthenticatorAssuranceLevel()` - If `currentLevel === 'aal1'` and `nextLevel === 'aal2'`, show TOTP input - Verify → `supabase.auth.mfa.challengeAndVerify()` 3. Add "Disable MFA" option with re-verification 4. Only show MFA options for email/password users (not OAuth) ### UX - Settings page: toggle to enable/disable MFA - Login flow: TOTP input step after password for enrolled users - Recovery: Supabase provides recovery codes during enrollment — display them ## Files to modify - `frontend/src/pages/` — new MFA settings component or add to existing profile page - `frontend/src/pages/Login.tsx` — add MFA challenge step - `frontend/src/contexts/AuthContext.tsx` — handle AAL levels ## Checklist - [x] Add MFA enrollment UI (QR code, verification) to profile/settings - [x] Display backup secret code after enrollment (Supabase TOTP doesn't provide recovery codes) - [x] Add TOTP challenge step to login flow - [x] Check AAL after login and redirect to TOTP if needed - [x] Add "Disable MFA" with re-verification - [x] Only show MFA options for email/password users - [ ] Test: full enrollment → login → TOTP flow - [N/A] Test: recovery code works when TOTP unavailable (Supabase doesn't provide recovery codes; users save their secret key instead)