Skip to main content
WebAuthn (Web Authentication) provides phishing-resistant authentication using:
  • Hardware security keys (YubiKey, Google Titan, etc.)
  • Platform authenticators (Touch ID, Face ID, Windows Hello)
  • Passkeys for passwordless authentication
WebAuthn implements the FIDO2 standard and uses public-key cryptography, making it resistant to phishing, credential stuffing, and man-in-the-middle attacks.

Installation

WebAuthn support requires the fido2 package:

Configuration

WebAuthn is disabled by default. Enable it in settings.py:
settings.py

Development Setup

For local development on localhost:
settings.py
Versions of fido2 up to 1.1.3 do not regard localhost as a secure origin. Set MFA_WEBAUTHN_ALLOW_INSECURE_ORIGIN = True only for local development, never in production.

URL Endpoints

WebAuthn URLs are available at:
  • /accounts/mfa/webauthn/add/ - Add a new WebAuthn authenticator
  • /accounts/mfa/webauthn/ - List all WebAuthn authenticators
  • /accounts/mfa/webauthn/<pk>/edit/ - Edit authenticator name
  • /accounts/mfa/webauthn/<pk>/delete/ - Remove an authenticator
  • /accounts/mfa/webauthn/login/ - Passwordless login endpoint
  • /accounts/mfa/webauthn/signup/ - Passwordless signup endpoint
  • /accounts/mfa/webauthn/reauthenticate/ - Reauthentication endpoint

Adding a WebAuthn Authenticator

Flow

  1. User navigates to /accounts/mfa/webauthn/add/
  2. Server generates a challenge and registration options
  3. User’s browser/device prompts for authentication (fingerprint, security key, etc.)
  4. Device creates a new key pair and returns the public key
  5. Server validates and stores the public key

Template Example

templates/mfa/webauthn/add_form.html

Passkey Login (Passwordless)

Passkeys allow users to log in without entering a username or password.

Enable Passkey Login

settings.py

How It Works

  1. User clicks “Sign in with passkey” button
  2. Browser prompts user to select a passkey
  3. User authenticates (fingerprint, face, security key)
  4. Server validates the signature and logs user in

Implementation Example

templates/account/login.html

Passkey Signup

Users can create an account using only a passkey, no password required.

Requirements

settings.py
Passkey signup requires email verification by code because the traditional email verification link approach needs a password, which passkey users don’t have.

Programmatic Usage

Begin Registration

Complete Registration

Begin Authentication

Complete Authentication

List User’s Authenticators

Customizing the Adapter

Customize WebAuthn behavior by overriding the adapter:
myapp/adapter.py
settings.py

Forms Customization

Override WebAuthn forms:
settings.py

Custom Add Form

myapp/forms.py

Database Model

WebAuthn credentials are stored in the Authenticator model:
The data field stores:

Security Features

Phishing Resistance

WebAuthn credentials are bound to your domain. They won’t work on phishing sites:

User Verification

For passwordless flows, require user verification (biometric/PIN):

Attestation

WebAuthn supports attestation to verify the authenticator’s authenticity. The fido2 library handles this automatically.

Browser Support

WebAuthn is supported in:
  • Chrome/Edge 67+
  • Firefox 60+
  • Safari 13+
  • Opera 54+

Feature Detection

Common Issues

”Localhost not secure” Error

In development, set:

Credentials Not Working Across Subdomains

Set the RP ID to the parent domain:

User Verification Fails

Some authenticators don’t support user verification. For non-passwordless flows, use:

Testing

WebAuthn requires HTTPS or localhost. For testing:
  1. Use python manage.py runserver (localhost)
  2. Or use a tool like ngrok for HTTPS tunneling
  3. Or configure MFA_WEBAUTHN_ALLOW_INSECURE_ORIGIN = True

Virtual Authenticators

Chrome DevTools supports virtual authenticators for testing:
  1. Open DevTools → More Tools → WebAuthn
  2. Enable virtual authenticator environment
  3. Add a virtual authenticator
  4. Test WebAuthn flows without physical hardware