Add MFA/2FA support via standalone sub-package#728
Conversation
1a0d03b to
f5755c1
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds comprehensive TOTP-based Multi-Factor Authentication (MFA) support to dj-rest-auth as an optional sub-package (dj_rest_auth.mfa). The implementation is opt-in and backward compatible - existing code is unaffected except for new settings defaults in app_settings.py and optional extras in setup.py.
Changes:
- Adds
dj_rest_auth.mfasub-package with models, views, serializers, and URLs for TOTP and recovery code authentication - Implements ephemeral token flow: users with MFA enabled receive a temporary signed token instead of immediate authentication, which must be exchanged with a valid TOTP/recovery code at
/mfa/verify/ - Includes comprehensive documentation in RST format and README with setup instructions, API endpoint descriptions, and usage examples
Reviewed changes
Copilot reviewed 18 out of 20 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| setup.py | Adds with-mfa extras requiring pyotp>=2.9.0 and qrcode>=8.0 |
| docs/mfa.rst | Complete 304-line MFA documentation covering installation, endpoints, configuration, and examples |
| docs/index.rst | Adds MFA documentation link to main index |
| docs/configuration.rst | Documents all MFA-related configuration settings |
| dj_rest_auth/tests/test_mfa.py | Comprehensive test suite with 28 tests including 19-step end-to-end flow |
| dj_rest_auth/tests/requirements.txt | Adds pyotp test dependency |
| dj_rest_auth/tests/mfa_urls.py | URL configuration for MFA tests |
| dj_rest_auth/mfa/views.py | Implements MFALoginView, MFAVerifyView, TOTPActivateView, TOTPDeactivateView, MFAStatusView, and recovery code management views |
| dj_rest_auth/mfa/utils.py | Ephemeral token creation/verification and MFA status checking utilities |
| dj_rest_auth/mfa/urls.py | URL patterns for all MFA endpoints |
| dj_rest_auth/mfa/totp.py | TOTP secret generation, validation, and management logic |
| dj_rest_auth/mfa/serializers.py | Serializers for MFA verification, TOTP activation/deactivation, status, and recovery codes |
| dj_rest_auth/mfa/recovery_codes.py | Recovery code generation, validation, and management with seed-based deterministic generation |
| dj_rest_auth/mfa/models.py | Authenticator model storing TOTP secrets and recovery code data in JSONField |
| dj_rest_auth/mfa/migrations/0001_initial.py | Initial migration creating Authenticator model with unique constraint on (user, type) |
| dj_rest_auth/mfa/apps.py | AppConfig for the MFA sub-package |
| dj_rest_auth/mfa/init.py | Empty init file for MFA package |
| dj_rest_auth/mfa/migrations/init.py | Empty init file for migrations |
| dj_rest_auth/app_settings.py | Adds MFA-related default settings and serializer import strings |
| README.md | Adds Quick MFA Setup section with installation instructions and login flow diagram |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 20 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 20 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 21 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Summary
Adds opt-in TOTP-based MFA as a standalone sub-package (
dj_rest_auth.mfa). If you don't enable it, nothing changes for you.This is a big diff (~6k lines added), but the majority of that is the demo app overhaul (new Next.js SPA + Docker setup, replacing the old React app). The actual MFA code is roughly 1,700 lines including tests.
How it works
Users add
dj_rest_auth.mfatoINSTALLED_APPS, install thewith-mfaextra, and swapLoginViewforMFALoginViewin their URL config. MFA is per-user. Users who haven't activated TOTP go through the normal login flow.For MFA-enabled users, login returns a short-lived signed ephemeral token instead of a real auth token. The client then sends that token plus a TOTP or recovery code to
/mfa/verify/to complete authentication.Endpoints
POST /mfa/verify/- complete MFA login with ephemeral token + codeGET /mfa/totp/activate/- get setup payload (secret, totp_url, activation_token)POST /mfa/totp/activate/- confirm activation with activation_token + codePOST /mfa/totp/deactivate/- disable TOTP (requires valid code)GET /mfa/status/- check whether MFA is enabledGET /mfa/recovery-codes/- view unused recovery codesPOST /mfa/recovery-codes/regenerate/- regenerate codesWhat changed since this PR was opened
hmac.compare_digest) for TOTP and recovery code validationselect_for_update()with atomic transactionslast_used_attracking on authenticator recordsSecurity notes
Dependencies
pyotp>=2.9.0via thewith-mfaextra (not a core dependency)qrcodeis fully optionalTests
48+ tests covering activation, deactivation, login flows (with and without JWT), expired/invalid tokens, replay attacks, race conditions, and audit logging. MFA tests use a separate URL config and
@modify_settingsso they don't touch the standard test suite.