Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication.
—
TOTP authenticators, WebAuthn hardware keys, recovery codes, and MFA management flows. Provides enterprise-grade security with support for multiple authentication factors including time-based codes, hardware security keys, and backup recovery codes.
Core models for managing MFA authenticators, recovery codes, and authentication sessions.
class Authenticator(models.Model):
"""
Base model for MFA authenticators (TOTP, WebAuthn, etc.).
"""
user: User = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
type: str = models.CharField(max_length=20)
data: dict = models.JSONField(default=dict)
created_at: datetime = models.DateTimeField(auto_now_add=True)
last_used_at: Optional[datetime] = models.DateTimeField(null=True, blank=True)
def __str__(self) -> str: ...
def record_usage(self) -> None: ...
class RecoveryCode(models.Model):
"""
Recovery codes for MFA account recovery.
"""
user: User = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
code: str = models.CharField(max_length=16)
used_at: Optional[datetime] = models.DateTimeField(null=True, blank=True)
def is_used(self) -> bool: ...
def use_code(self) -> None: ...
class AuthenticationSession(models.Model):
"""
Track MFA authentication sessions.
"""
user: User = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
created_at: datetime = models.DateTimeField(auto_now_add=True)
expires_at: datetime = models.DateTimeField()
token: str = models.CharField(max_length=255)
def is_expired(self) -> bool: ...TOTP authenticator implementation using standard RFC 6238.
class TOTPAuthenticator:
"""
Time-based One-Time Password authenticator.
"""
def __init__(self, authenticator: Authenticator): ...
def generate_qr_code(self, name: str = None) -> str:
"""
Generate QR code URL for TOTP setup.
Parameters:
- name: Optional name for the account
Returns:
QR code data URL
"""
def get_secret_key(self) -> str:
"""
Get the secret key for manual entry.
Returns:
Base32-encoded secret key
"""
def validate_token(self, token: str) -> bool:
"""
Validate TOTP token.
Parameters:
- token: 6-digit TOTP code
Returns:
True if token is valid
"""
@classmethod
def generate_secret(cls) -> str:
"""
Generate new TOTP secret.
Returns:
Base32-encoded secret
"""
def get_totp_key(user: User) -> str:
"""
Get or generate TOTP secret key for user.
Parameters:
- user: User instance
Returns:
TOTP secret key
"""
def validate_totp_token(user: User, token: str) -> bool:
"""
Validate TOTP token for user.
Parameters:
- user: User instance
- token: TOTP token to validate
Returns:
True if token is valid
"""WebAuthn implementation for hardware security keys and platform authenticators.
class WebAuthnAuthenticator:
"""
WebAuthn hardware security key authenticator.
"""
def __init__(self, authenticator: Authenticator): ...
def get_credential_creation_options(self, request: HttpRequest) -> Dict[str, Any]:
"""
Get options for WebAuthn credential creation.
Parameters:
- request: HTTP request object
Returns:
WebAuthn creation options dictionary
"""
def verify_registration(self, request: HttpRequest, credential: Dict[str, Any]) -> bool:
"""
Verify WebAuthn registration.
Parameters:
- request: HTTP request object
- credential: WebAuthn credential data
Returns:
True if registration is valid
"""
def get_credential_request_options(self, request: HttpRequest) -> Dict[str, Any]:
"""
Get options for WebAuthn authentication.
Parameters:
- request: HTTP request object
Returns:
WebAuthn request options dictionary
"""
def verify_authentication(self, request: HttpRequest, credential: Dict[str, Any]) -> bool:
"""
Verify WebAuthn authentication.
Parameters:
- request: HTTP request object
- credential: WebAuthn credential data
Returns:
True if authentication is valid
"""
def get_webauthn_rp_id(request: HttpRequest) -> str:
"""
Get WebAuthn Relying Party ID from request.
Parameters:
- request: HTTP request object
Returns:
RP ID string
"""
def get_webauthn_origin(request: HttpRequest) -> str:
"""
Get WebAuthn origin from request.
Parameters:
- request: HTTP request object
Returns:
Origin URL string
"""Recovery code generation and management for MFA account recovery.
def generate_recovery_codes(user: User, count: int = 10) -> List[str]:
"""
Generate recovery codes for user.
Parameters:
- user: User instance
- count: Number of codes to generate
Returns:
List of recovery code strings
"""
def validate_recovery_code(user: User, code: str) -> bool:
"""
Validate and consume recovery code.
Parameters:
- user: User instance
- code: Recovery code to validate
Returns:
True if code is valid and unused
"""
def get_unused_recovery_codes(user: User) -> List[RecoveryCode]:
"""
Get unused recovery codes for user.
Parameters:
- user: User instance
Returns:
List of unused RecoveryCode instances
"""
def regenerate_recovery_codes(user: User) -> List[str]:
"""
Regenerate all recovery codes for user.
Parameters:
- user: User instance
Returns:
List of new recovery code strings
"""Django views for MFA setup, authentication, and management.
class AuthenticateView(FormView):
"""
MFA authentication view.
"""
template_name: str = "mfa/authenticate.html"
form_class: type = AuthenticateForm
def get_form_kwargs(self) -> Dict[str, Any]: ...
def form_valid(self, form: AuthenticateForm) -> HttpResponse: ...
class TOTPAddView(FormView):
"""
Add TOTP authenticator view.
"""
template_name: str = "mfa/totp/add.html"
form_class: type = TOTPAddForm
def get_context_data(self, **kwargs) -> Dict[str, Any]: ...
def form_valid(self, form: TOTPAddForm) -> HttpResponse: ...
class TOTPRemoveView(FormView):
"""
Remove TOTP authenticator view.
"""
template_name: str = "mfa/totp/remove.html"
form_class: type = TOTPRemoveForm
class WebAuthnAddView(FormView):
"""
Add WebAuthn authenticator view.
"""
template_name: str = "mfa/webauthn/add.html"
form_class: type = WebAuthnAddForm
def get_context_data(self, **kwargs) -> Dict[str, Any]: ...
class RecoveryCodesView(TemplateView):
"""
Recovery codes management view.
"""
template_name: str = "mfa/recovery_codes/index.html"
def get_context_data(self, **kwargs) -> Dict[str, Any]: ...
class RecoveryCodesGenerateView(FormView):
"""
Generate new recovery codes view.
"""
template_name: str = "mfa/recovery_codes/generate.html"
form_class: type = GenerateRecoveryCodesForm
def form_valid(self, form: GenerateRecoveryCodesForm) -> HttpResponse: ...Django forms for MFA setup and authentication.
class AuthenticateForm(forms.Form):
"""
MFA authentication form.
"""
code: str = forms.CharField(max_length=16)
def __init__(self, user: User, request: HttpRequest, *args, **kwargs): ...
def clean_code(self) -> str: ...
class TOTPAddForm(forms.Form):
"""
TOTP setup form.
"""
secret: str = forms.CharField(widget=forms.HiddenInput)
code: str = forms.CharField(max_length=6)
def __init__(self, user: User, *args, **kwargs): ...
def clean_code(self) -> str: ...
def save(self) -> Authenticator: ...
class TOTPRemoveForm(forms.Form):
"""
TOTP removal form.
"""
authenticator: int = forms.ModelChoiceField(queryset=None)
def __init__(self, user: User, *args, **kwargs): ...
def save(self) -> None: ...
class WebAuthnAddForm(forms.Form):
"""
WebAuthn setup form.
"""
name: str = forms.CharField(max_length=100)
credential: str = forms.CharField(widget=forms.HiddenInput)
def __init__(self, user: User, request: HttpRequest, *args, **kwargs): ...
def save(self) -> Authenticator: ...
class GenerateRecoveryCodesForm(forms.Form):
"""
Recovery code generation form.
"""
def __init__(self, user: User, *args, **kwargs): ...
def save(self) -> List[str]: ...MFA utility functions and helpers.
def is_mfa_enabled(user: User) -> bool:
"""
Check if user has MFA enabled.
Parameters:
- user: User instance
Returns:
True if user has any MFA authenticators
"""
def get_user_authenticators(user: User, authenticator_type: str = None) -> QuerySet:
"""
Get user's MFA authenticators.
Parameters:
- user: User instance
- authenticator_type: Optional filter by authenticator type
Returns:
QuerySet of Authenticator instances
"""
def create_authentication_session(user: User) -> AuthenticationSession:
"""
Create MFA authentication session.
Parameters:
- user: User instance
Returns:
AuthenticationSession instance
"""
def verify_authentication_session(token: str) -> Optional[AuthenticationSession]:
"""
Verify MFA authentication session token.
Parameters:
- token: Session token
Returns:
AuthenticationSession instance if valid, None otherwise
"""from allauth.mfa.totp import TOTPAuthenticator, get_totp_key
from allauth.mfa.models import Authenticator
# Generate TOTP secret for user
secret = get_totp_key(user)
# Create authenticator
authenticator = Authenticator.objects.create(
user=user,
type='totp',
data={'secret': secret}
)
# Generate QR code for setup
totp_auth = TOTPAuthenticator(authenticator)
qr_code_url = totp_auth.generate_qr_code(f"{user.username}@example.com")
# Validate TOTP token
is_valid = totp_auth.validate_token('123456')from allauth.mfa.webauthn import WebAuthnAuthenticator
from allauth.mfa.models import Authenticator
# Create WebAuthn authenticator
authenticator = Authenticator.objects.create(
user=user,
type='webauthn',
data={}
)
webauthn_auth = WebAuthnAuthenticator(authenticator)
# Get registration options (send to frontend)
creation_options = webauthn_auth.get_credential_creation_options(request)
# Verify registration (after credential creation)
credential_data = {
'id': 'credential_id',
'rawId': 'raw_credential_id',
'response': {
'attestationObject': 'attestation_data',
'clientDataJSON': 'client_data'
}
}
is_valid = webauthn_auth.verify_registration(request, credential_data)from allauth.mfa.recovery_codes import (
generate_recovery_codes,
validate_recovery_code,
get_unused_recovery_codes
)
# Generate recovery codes
codes = generate_recovery_codes(user, count=10)
print("Recovery codes:", codes)
# Validate and use recovery code
is_valid = validate_recovery_code(user, 'ABC123DEF')
# Check remaining codes
remaining_codes = get_unused_recovery_codes(user)
print(f"Remaining codes: {len(remaining_codes)}")from allauth.mfa.utils import is_mfa_enabled, create_authentication_session
# Check if user has MFA enabled
if is_mfa_enabled(user):
# Create authentication session
session = create_authentication_session(user)
# Store session token (e.g., in session or redirect parameter)
request.session['mfa_session_token'] = session.token
# Redirect to MFA authentication page
return redirect('mfa_authenticate')<!-- MFA status in user profile -->
{% if user.is_authenticated %}
{% load mfa_tags %}
<h3>Multi-Factor Authentication</h3>
{% if user|is_mfa_enabled %}
<p class="text-success">✓ MFA is enabled</p>
<!-- Show authenticators -->
{% for auth in user.authenticator_set.all %}
<div class="authenticator">
<strong>{{ auth.get_type_display }}</strong>
<small>Added {{ auth.created_at|date }}</small>
</div>
{% endfor %}
<a href="{% url 'mfa_recovery_codes' %}">View Recovery Codes</a>
{% else %}
<p class="text-warning">⚠ MFA is not enabled</p>
<a href="{% url 'mfa_add_totp' %}" class="btn btn-primary">Enable TOTP</a>
<a href="{% url 'mfa_add_webauthn' %}" class="btn btn-secondary">Add Security Key</a>
{% endif %}
{% endif %}# In Django settings.py
# Enable MFA
INSTALLED_APPS = [
# ...
'allauth.mfa',
]
# MFA settings
MFA_TOTP_ISSUER = 'My Application'
MFA_RECOVERY_CODE_COUNT = 10
MFA_WEBAUTHN_RP_NAME = 'My Application'
# Require MFA for certain views
MFA_REQUIRED_FOR_STAFF = True
MFA_GRACE_PERIOD_SECONDS = 300 # 5 minutesInstall with Tessl CLI
npx tessl i tessl/pypi-django-allauth