django-two-factor-auth

Complete two-factor authentication for Django, adding TOTP, SMS/call, email, WebAuthn, and YubiKey verification on top of django-otp.

Library
PyPI
v1.18.1
1,878stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
75/100Good
Development Activity72
Maintenance48
Community80
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
81/100Excellent
Architecture80
Code Quality78
Innovation75
Learning Curve90

django-two-factor-auth is a reusable Django app that adds a full second-authentication-factor flow on top of Django’s built-in django.contrib.auth and the django-otp one-time-password framework. Instead of reinventing token storage, it wraps django-otp’s device model with wizard-based setup and login views (built on django-formtools’ SessionWizardView), so users can enroll a TOTP authenticator app, receive an SMS/voice call via Twilio, get an emailed code, or register a WebAuthn/YubiKey hardware key.

Verification methods are pluggable: each is a separate Django app under two_factor.plugins.* that registers itself with a central MethodRegistry, and urls.py auto-discovers installed plugin apps at runtime to mount their URLs. This lets a project opt into only the methods it needs via pip extras (call, sms, webauthn, yubikey, phonenumbers) without touching the core package. Backup one-time-use recovery tokens, an admin integration for support staff, and translations for dozens of locales round out the package, which has been maintained under the Jazzband collective since 2014 and supports current Django (4.2–6.0) and Python (3.11–3.14) versions.

What You Get

  • A ready-to-include two_factor/urls.py covering login, setup, QR code generation, and backup-token views
  • Opt-in plugin packages per project: SMS/voice via Twilio, WebAuthn, YubiKey hardware keys, and email codes
  • A MethodRegistry extension point so third-party packages can add new verification methods without patching core views
  • Translation files for dozens of locales shipped in two_factor/locale
  • An example Django project demonstrating the full setup (excluding the Twilio integration)

Common Use Cases

  • Adding a second authentication factor to an existing Django auth system without replacing it
  • Meeting security or compliance requirements for admin dashboards and internal tooling
  • Letting users choose between TOTP app, SMS, email, or hardware-key verification
  • Recovering account access via one-time backup tokens when a primary device is lost

Under The Hood

Architecture The package is a standard reusable Django app: two_factor/views/core.py holds the multi-step LoginView and SetupView built on django-formtools’ SessionWizardView, while two_factor/plugins/ houses independent Django apps (email, phonenumber, webauthn, yubikey) that each register a verification method with the MethodRegistry singleton in plugins/registry.py. urls.py walks Django’s app registry at import time, discovering any installed two_factor.plugins.* app and mounting its own urls module under a per-plugin path prefix, so adding or removing a verification method is a matter of installing/uninstalling a Django app rather than editing core routing. A small thread-local middleware exposes the current request to signal handlers. The core package does not model devices itself — it delegates all token persistence and verification to django-otp, treating it as the source of truth for enrolled devices.

Tech Stack Built for Django 4.2 through 6.0 and Python 3.11–3.14, with a required dependency on django_otp, qrcode, django-phonenumber-field, and django-formtools, plus optional extras for twilio (call/SMS), webauthn, django-otp-yubikey, and phonenumbers/phonenumberslite. CI runs the full version matrix through tox and GitHub Actions, with a separate code-quality job enforcing ruff and isort, and coverage tracked via Codecov. Documentation is built with Sphinx and hosted on Read the Docs.

Code Quality The test suite spans nineteen test_*.py modules covering every view (login, setup, backup tokens, disable, profile, QR code, phone), the plugin registry, forms, gateways, admin integration, management commands, and system checks, using Django’s TestCase, freezegun for time-dependent TOTP assertions, and mock for signal verification. The codebase favors explicit registry exceptions (MethodNotFoundError) over silent fallbacks, follows consistent snake_case naming, and is linted with ruff and isort in CI, though it carries no static type annotations or mypy checking.

API Design Adopting the package means adding two_factor and django_otp to INSTALLED_APPS and swapping in its login view — the wizard-based SetupView/LoginView absorb the multi-step form-state boilerplate a team would otherwise hand-roll. The MethodRegistry extension point is the most distinctive design choice: it lets a project or third-party package add an entirely new verification method as an installable Django app, without any changes to the core views or URLs, which is more extensible than most Django 2FA add-ons that hard-code their supported methods.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search