WebAuthn Protocol
Deep dive into the WebAuthn specification and implementation details. WebAuthn Guide →
Passkeys represent the biggest shift in authentication since passwords were invented:
| The Password Problem | The Passkey Solution |
|---|---|
| Users reuse passwords across sites | Unique cryptographic key per site |
| Passwords can be phished | Cryptographically bound to domain |
| Passwords are stored on servers | Only public key stored, private never leaves device |
| Users forget passwords | Biometric unlock, nothing to remember |
| Password reset is expensive | No passwords to reset |
Industry Adoption (2024):
Passkeys use asymmetric (public-key) cryptography:
Device generates a unique key pair. Private key stays on device (protected by biometrics). Public key is sent to the website.
Website sends a random challenge. Device signs the challenge with the private key (after biometric verification). Website verifies signature with stored public key.
If signature is valid, the user is authenticated. No password transmitted. No shared secret on the server.
The key insight: Passkeys are cryptographically bound to the website’s origin.
Example: You register a Passkey for bank.com
Legitimate site (bank.com):→ Browser confirms origin is "bank.com"→ Passkey for "bank.com" is used→ Authentication succeeds ✅
Phishing site (bank-secure.com):→ Browser confirms origin is "bank-secure.com"→ No Passkey exists for this domain→ Authentication fails ❌→ Phishing attack blocked automaticallyThe browser enforces origin checking at the protocol level. Users can’t be tricked into using their Passkey on a fake site, even if it looks identical.
Device-Bound Passkeys stay on one device and cannot be exported.
Examples:
Pros:
Cons:
Synced Passkeys are stored in a cloud-synced credential manager.
Examples:
Pros:
Cons:
Hardware Security Keys are physical devices (USB/NFC).
Examples:
Pros:
Cons:
Best for: Privileged accounts, high-security requirements
| Aspect | Password + MFA | Passkey |
|---|---|---|
| Phishing resistance | ❌ Codes can be phished in real-time | ✅ Cryptographically impossible |
| User experience | 😐 Type password, wait for code, enter code | 😊 One touch (Face ID/fingerprint) |
| Password resets | ❌ 30-40% of help desk calls | ✅ None — nothing to forget |
| Credential stuffing | ❌ Reused passwords are vulnerable | ✅ Unique key per site |
| Server breach impact | ❌ Hashed passwords can be cracked | ✅ Public keys are useless to attackers |
| Account recovery | Via email (another password) | Via synced credential manager |
Passkeys provide better security AND better UX. This is rare in security.
The WebAuthn JavaScript API:
// REGISTRATION: Create a new Passkeyconst credential = await navigator.credentials.create({ publicKey: { challenge: new Uint8Array([/* server-generated challenge */]), rp: { name: "Example Corp", id: "example.com" }, user: { id: new Uint8Array([/* unique user id */]), name: "jane@example.com", displayName: "Jane Doe" }, pubKeyCredParams: [ { alg: -7, type: "public-key" }, // ES256 { alg: -257, type: "public-key" } // RS256 ], authenticatorSelection: { residentKey: "preferred", userVerification: "preferred" }, timeout: 60000 }});
// Send credential.response to server for storage// AUTHENTICATION: Use an existing Passkeyconst assertion = await navigator.credentials.get({ publicKey: { challenge: new Uint8Array([/* server-generated challenge */]), rpId: "example.com", userVerification: "preferred", timeout: 60000 }});
// Send assertion.response to server for verificationDon’t implement WebAuthn from scratch. Use these:
| Language | Library |
|---|---|
| JavaScript | SimpleWebAuthn, @github/webauthn-json |
| Python | py_webauthn, fido2 |
| Node.js | SimpleWebAuthn, fido2-lib |
| Go | go-webauthn/webauthn |
| Ruby | webauthn-ruby |
| Java | java-webauthn-server |
// Enable Passkeys in Auth0// Dashboard → Authentication → Database → Password Policy// Enable "Passkey" authentication
// Or via Management API:const auth0 = new ManagementClient({...});await auth0.connections.update( { id: connectionId }, { options: { passkey: { enabled: true } } });Admin Console → Security → Authenticators→ Add Authenticator → FIDO2 (WebAuthn)
Configure:- User verification: Preferred or Required- Authenticator attachment: Platform, Cross-Platform, or Any- Resident key: Required (for usernameless login)Entra Admin Center → Authentication methods→ FIDO2 security key→ Enable → Configure target users/groups
For Passkeys (Preview):→ Enable "Passkeys (FIDO2)" under Authentication methods→ Configure allowed AAGUID if restricting authenticatorsCurrent state: Password + MFA↓Add Passkey as optional login methodUsers can register Passkeys while keeping passwordActions:
Login flow:1. Check if user has registered Passkey2. If yes → Offer Passkey login first3. If no → Fall back to password4. Prompt password users to register PasskeyActions:
For privileged users/sensitive apps:├── Require Passkey registration├── Disable password authentication└── Hardware keys for admin accessActions:
Target state:├── All users authenticate with Passkeys├── No passwords to phish, leak, or reset├── Hardware keys for privileged access└── Password only for legacy edge cases”Add Passkey” button in security settings or post-login prompt.
System dialog appears asking to create a Passkey for this site.
Face ID, Touch ID, Windows Hello, or security key touch.
Passkey saved. User can now sign in without a password.
1. User navigates to login page2. Clicks "Sign in with Passkey" (or autofill suggestion appears)3. Biometric prompt (Face ID, Touch ID, etc.)4. Authenticated! (< 3 seconds total)No typing. No waiting for SMS. No copying codes.
Problem: User loses all devices with synced Passkeys.
Solutions:
| Approach | Implementation |
|---|---|
| Multiple devices | Encourage registering Passkeys on multiple devices |
| Backup codes | Provide one-time recovery codes at registration |
| Hardware key backup | Register a security key stored in safe location |
| Identity verification | Help desk with strong identity proofing |
Problem: Can’t use personal Passkey on shared computer.
Solutions:
Problem: Apple Passkeys don’t sync to Android, and vice versa.
Solutions:
| Platform | Passkey Support |
|---|---|
| Chrome | ✅ Full support (synced via Google account) |
| Safari | ✅ Full support (synced via iCloud Keychain) |
| Edge | ✅ Full support (synced via Microsoft account) |
| Firefox | ✅ Support for hardware keys, synced Passkeys coming |
| iOS | ✅ Full support (Safari, supported apps) |
| Android | ✅ Full support (Chrome, supported apps) |
| Windows | ✅ Windows Hello, hardware keys |
| macOS | ✅ Touch ID, hardware keys |
| Attack | Protection Level | How |
|---|---|---|
| Phishing | ✅ Complete | Origin binding at protocol level |
| Credential stuffing | ✅ Complete | Unique key per site |
| Server breach | ✅ Complete | Only public keys stored |
| Keyloggers | ✅ Complete | No typing involved |
| SIM swapping | ✅ Complete | No phone numbers involved |
| MFA fatigue | ✅ Complete | No push notifications |
| Attack | Notes |
|---|---|
| Device theft | Biometrics help, but device access is a risk |
| Malware on device | Advanced malware could intercept authentication |
| Cloud account compromise | Synced Passkeys only as secure as the sync account |
| Social engineering | Users could be tricked into actions post-authentication |
WebAuthn Protocol
Deep dive into the WebAuthn specification and implementation details. WebAuthn Guide →
Passwordless Patterns
Explore passwordless authentication strategies beyond Passkeys. Passwordless Guide →
MFA Best Practices
Compare Passkeys with other MFA methods and plan your strategy. MFA Guide →
Zero Trust
Understand how Passkeys fit into a Zero Trust architecture. Zero Trust Guide →