Skip to main content

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

  1. User logs in with email and password (via allauth)
  2. The custom AccountAdapter checks if the user has OTP devices
  3. If OTP is enabled, login is interrupted and the user is redirected to /accounts/login/otp/
  4. User enters their TOTP code (or a backup code)
  5. 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:

URLViewPurpose
/accounts/otp/settings/OTPSettingsViewView 2FA status
/accounts/otp/setup/OTPSetupViewStart TOTP setup (shows QR code)
/accounts/otp/verify-setup/OTPVerifySetupViewConfirm setup with a code
/accounts/otp/backup-codes/OTPBackupCodesViewView backup codes
/accounts/otp/disable/OTPDisableViewDisable 2FA
/accounts/otp/regenerate-backup-codes/OTPRegenerateBackupCodesViewGenerate new backup codes
/accounts/login/otp/OTPLoginViewEnter 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.