Two-Factor Authentication
Overview
SpeedPy includes two-factor authentication (2FA) powered by django-otp. Users can enable TOTP (Time-based One-Time Password) with any authenticator app and generate backup codes for recovery.
How It Works
- User logs in with email and password (via allauth)
- The custom
AccountAdapterchecks if the user has OTP devices - If OTP is enabled, login is interrupted and the user is redirected to
/accounts/login/otp/ - User enters their TOTP code (or a backup code)
- On successful verification, the login completes
This flow works for both email/password and social logins (GitHub, Google, GitLab).
Installed Apps & Middleware
INSTALLED_APPS = [
...
"django_otp",
"django_otp.plugins.otp_totp",
"django_otp.plugins.otp_static",
...
]
MIDDLEWARE = [
...
"django_otp.middleware.OTPMiddleware",
...
]
URL Routes
All OTP management routes are in mainapp/urls.py:
| URL | View | Purpose |
|---|---|---|
/accounts/otp/settings/ | OTPSettingsView | View 2FA status |
/accounts/otp/setup/ | OTPSetupView | Start TOTP setup (shows QR code) |
/accounts/otp/verify-setup/ | OTPVerifySetupView | Confirm setup with a code |
/accounts/otp/backup-codes/ | OTPBackupCodesView | View backup codes |
/accounts/otp/disable/ | OTPDisableView | Disable 2FA |
/accounts/otp/regenerate-backup-codes/ | OTPRegenerateBackupCodesView | Generate new backup codes |
/accounts/login/otp/ | OTPLoginView | Enter OTP during login |
Configuration
OTP_TOTP_ISSUER = env.str("OTP_TOTP_ISSUER", default="uptimefor.me")
OTP_LOGIN_URL = reverse_lazy("account_login_otp")
Set OTP_TOTP_ISSUER to your app name — this is what users see in their authenticator app.
QR Code Generation
SpeedPy includes the qrcode package for generating QR codes during TOTP setup. Users scan the QR code with their authenticator app (Google Authenticator, Authy, 1Password, etc.).
Backup Codes
When a user enables 2FA, static backup codes are generated via django_otp.plugins.otp_static. These one-time codes can be used if the user loses access to their authenticator app.