Auth: Add 2FA requirement to magic link login flow
Resolved 💬 3 comments Opened Nov 26, 2025 by cjamanambu Closed Jan 26, 2026
Summary
Add 2FA (TOTP) verification requirement to magic link login when users have mfaPreference.twoFA enabled, matching the security of password login.
Current Behavior
- Password login (
post-login-password.ts) checksmfaPreference.twoFAand requires TOTP before issuing JWT - Magic link login (
post-verify-login.ts,post-verify-login-worker.ts) skips 2FA entirely and issues JWT immediately
Proposed Implementation
Use the Intermediate Session Token (IST) pattern (industry standard used by Stytch, Auth0):
Flow
- User clicks magic link
POST /auth/v1/login/verify { magicToken }
- If 2FA enabled: returns
{ intermediateToken, state: ONE, mfaRequired: true } - If no 2FA: returns
{ accessToken, state: TWO }(current behavior)
POST /auth/v1/login/verify { intermediateToken, token: "123456" }
- Validates IST + TOTP → returns
{ accessToken, state: TWO }
Why IST Pattern
- Magic link stays one-time use (consumed immediately)
- IST is short-lived (10 minutes) reducing attack window
- Clean separation of authentication stages
- Industry standard approach
Files to Modify
services/auth/handlers/post-verify-login.ts- Add 2FA check for integratorsservices/auth/handlers/post-verify-login-worker.ts- Add 2FA check for workerslib/schemas/models/session.ts- Add IST creation/validation functionsservices/auth/schema/request/- Update request schemas to accept intermediateToken + token
Acceptance Criteria
- [ ] Magic link login requires 2FA when
mfaPreference.twoFAis enabled - [ ] Intermediate tokens expire after 10 minutes
- [ ] Intermediate tokens are one-time use
- [ ] Existing flow unchanged when 2FA not enabled
- [ ] Works for both integrators and workers/admins
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗