Skip to main content
TOTP (Time-based One-Time Password) authentication allows users to generate temporary codes using authenticator apps like Google Authenticator, Authy, 1Password, or Microsoft Authenticator.

How It Works

TOTP generates six-digit codes that change every 30 seconds based on:
  • A shared secret key stored in your database
  • The current time
  • The HMAC-SHA1 algorithm
When a user sets up TOTP:
  1. A random secret is generated
  2. The secret is encoded as a QR code
  3. User scans the QR code with their authenticator app
  4. User enters a code from their app to verify setup
  5. The secret is encrypted and stored in the database

Configuration

TOTP is enabled by default. Configure it in settings.py:
settings.py

Settings Reference

MFA_TOTP_PERIOD

Default: 30 The number of seconds a TOTP code remains valid.

MFA_TOTP_DIGITS

Default: 6 The number of digits in generated codes. Most authenticator apps support 6 or 8 digits.

MFA_TOTP_ISSUER

Default: "" (uses site name) The issuer name displayed in authenticator apps. Helps users identify which account the code is for.

MFA_TOTP_TOLERANCE

Default: 0 Number of time periods (past and future) to accept. Helps with clock drift between server and client.
Higher tolerance values are less secure but more tolerant of clock drift. Use 0 for maximum security or 1 for better user experience.

URL Endpoints

TOTP URLs are available at:
  • /accounts/mfa/totp/activate/ - Activate TOTP authentication
  • /accounts/mfa/totp/deactivate/ - Deactivate TOTP authentication

Activation Flow

Users can activate TOTP through the ActivateTOTPView:

Template Context

The activation template receives:

Custom Template Example

templates/mfa/totp/activate_form.html

Programmatic Usage

Generate and Validate Codes

Activate TOTP for a User

Check if User Has TOTP Enabled

Validate TOTP During Login

Customizing Forms

Override the default forms in settings.py:
settings.py

Custom Activation Form

myapp/forms.py

Customizing the TOTP URL

Override the adapter to customize QR code generation:
myapp/adapter.py
settings.py

Security Considerations

Secret Storage

TOTP secrets are stored encrypted in the database:
To add custom encryption, override the adapter:

Code Reuse Prevention

TOTP codes are cached after use to prevent replay attacks:

Development & Testing

Bypass Code for Testing

Only use this in development environments with DEBUG = True.
settings.py
This allows you to use 123456 as a valid code during testing, regardless of the actual TOTP value.

Recovery Codes

When users activate TOTP, recovery codes are automatically generated. This ensures users can access their account if they lose their authenticator device. Learn more about recovery codes →

Common Issues

Clock Drift

If users report codes not working:

QR Code Not Displaying

Ensure qrcode is installed:

Codes Not Accepted

Check that django.contrib.messages is installed and configured: