Opt-in SMS two-factor auth (Twilio Verify) #739
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Demoted from draft PR #173 (branch
feature/sms-2fa, now closed) to keep it on the backlog rather than as a stale open PR. The draft was built against a very oldmain(migration0020_user_phone, references to the retired startup healing DDL, route-count 289→293) so it needs a fresh rebuild — but the design below is sound and worth keeping.Goal
Opt-in SMS second factor on password login across backend, web, and mobile. A user enables it in settings, registers a phone, and every subsequent password login then requires a texted 6-digit code. Nobody is affected until they opt in.
Design (from the draft)
User.phone).mfa_enabled→ server texts a code and returns a short-lived,typ-scoped challenge JWT (no server-side challenge table). Client completes atPOST /auth/login/verifywith challenge token + code → real access JWT./auth/mfa/enroll/start(store phone, text code) →/auth/mfa/enroll/verify(confirm + enable). Disable:/auth/mfa/disable.TWILIO_ACCOUNT_SID/TWILIO_AUTH_TOKEN/TWILIO_VERIFY_SERVICE_SIDare set. Dev/design: unconfigured service acceptsMFA_DEV_BYPASS_CODE; production-likeAPP_ENVfails CLOSED (503) instead of accepting the bypass./firebase,/apple) exempt — the provider already supplied a second factor. (Open question: gate them too?)Surfaces
User.phone(+ a fresh migration on current head — NOT the old 0020),services/sms_2fa.py, challenge-token helpers, login gate + 4 routes.mfaview on login page; enroll/disable card in/settings.verify-2fa+security-2fascreens;AuthProvidertwo-step login + enroll helpers.Known ceilings to resolve on rebuild
+1auto-prefix).Filed from a Claude Code session