django-multifactor

Drop-in multi-factor authentication for Django. Ships with standalone views, opinionated defaults, and a very simple integration pathway to retrofit onto mature sites.

django-multifactor is a second layer of defence, not a passwordless system. It sits on top of Django’s existing authentication and asks a logged-in user to prove themselves with a second factor before sensitive views render.

Supported factors:

  • FIDO2 / WebAuthn — security keys, Windows Hello, Touch ID, Android SafetyNet, NFC.

  • TOTP — any RFC 6238 authenticator app (Google Authenticator, Authy, 1Password, Bitwarden, …).

  • Fallback OTP — pluggable transports (email by default, plus anything you bolt on — SMS, push, in-app messaging, carrier pigeon).

Note

U2F was removed in version 0.6. If you still depend on U2F, pin to an older release and plan a migration to FIDO2.

Who this site is for

This documentation is written so that a junior developer can get a working MFA flow in their Django project in under an hour, while still giving senior developers the architectural depth, security model, and tuning knobs they need to deploy django-multifactor to production with confidence.

If you are brand new, start with Installation and follow the chapters in order. If you have used django-multifactor before, the Reference and Debugging sections are probably what you want.

How the docs are organised

Section

Audience

What you’ll find

Getting started

Junior

Install, configure, protect your first view.

Concepts

All

How the package is wired together; full request flow diagrams.

Guides

All

Task-oriented recipes — admin integration, custom fallbacks, branding, i18n.

Reference

All

Every setting, decorator, mixin, model field and named URL.

Security

Senior

Threat model, hardening, fallback risk, recheck tuning.

Debugging

Senior

Troubleshooting recipes, logging configuration, the bundled testsite.

Contributing

Contributors

Local development, the test matrix, translations, releases.

A 10-second taste

# settings.py
INSTALLED_APPS = [
    # ...
    "django.contrib.messages",
    "multifactor",
]

MULTIFACTOR = {
    "FIDO_SERVER_ID": "example.com",
    "FIDO_SERVER_NAME": "My Django App",
    "TOKEN_ISSUER_NAME": "My Django App",
}
# urls.py
from django.urls import include, path

urlpatterns = [
    path("admin/multifactor/", include("multifactor.urls")),
    # ...
]
# views.py
from multifactor.decorators import multifactor_protected


@multifactor_protected(factors=1)
def billing(request): ...

That’s it — every user with one or more registered second factors will be sent through MFA challenge before billing renders.

Table of contents

Guides

Debugging

Changelog