How Passwordless Login Works Under the Hood
You click “Sign in,” your phone asks for a fingerprint, and you’re authenticated. No password typed, no code copied from an email. If you’ve implemented authentication flows before, this probably feels like magic—or worse, a black box you’re expected to integrate without understanding.
This article explains how passkeys and WebAuthn actually work beneath the browser APIs. You’ll understand the authentication flow, the cryptographic primitives involved, and the security properties that make FIDO2-based passwordless authentication fundamentally different from older approaches like magic links or OTPs.
Key Takeaways
- Passkeys use public-key cryptography where the private key never leaves your device, eliminating shared secrets that attackers can intercept or steal.
- WebAuthn authentication involves four parties: your frontend, the browser API, the authenticator (device keychain or hardware key), and your server.
- Origin binding provides cryptographic phishing resistance—credentials are bound to specific domains and won’t work on lookalike sites.
- Conditional UI allows passkey prompts to appear in autofill suggestions, creating seamless authentication experiences.
Why Passkeys Replaced Earlier “Passwordless” Methods
Magic links and one-time passwords removed the password field from login forms, but they didn’t eliminate shared secrets. A magic link is still a bearer token transmitted through email—interceptable, replayable, and phishable if users click links on spoofed domains. OTPs sent via SMS are vulnerable to SIM-swapping attacks.
Passkeys solve this differently. They use public-key cryptography where the secret (your private key) never leaves your device and never travels over the network. The server only stores your public key, which is useless to attackers even if the database is breached.
This is the core insight behind FIDO2 and WebAuthn: authentication happens through cryptographic proof of possession, not transmission of secrets.
The WebAuthn Authentication Flow
When a user authenticates with a passkey, four components typically interact: your frontend code, the browser’s WebAuthn API, the authenticator (often the OS keychain, a phone, or a hardware security key), and your server.
Registration: Creating the Credential
During registration, your server generates a challenge—a random byte sequence—and sends it to the browser along with your relying party ID (typically your domain). Your frontend calls navigator.credentials.create() with these parameters.
The browser hands this request to the authenticator via CTAP (Client to Authenticator Protocol). The authenticator generates a new key pair, stores the private key securely, and returns the public key along with a signed attestation.
Your server receives and stores the public key, the credential ID, and metadata like a signature counter. No password hash, no shared secret—just a public key scoped to your domain.
Authentication: Proving Possession
When the user returns, your server generates a fresh challenge. Your frontend calls navigator.credentials.get(), and the browser prompts the authenticator.
The authenticator finds the credential matching your RP ID, requires user verification (biometric, PIN, or presence), then signs the challenge with the private key. This signature, along with authenticator data, returns to your server.
Your server verifies the signature against the stored public key. If it matches, the user proved they possess the private key without ever transmitting it.
Origin Binding: The Phishing Resistance Mechanism
Here’s what makes passkeys genuinely phishing-resistant rather than just “harder to phish.” The authenticator cryptographically binds credentials to the relying party’s origin.
When signing the challenge, the authenticator includes the relying party ID hash (derived from your domain) in the signed data. If an attacker creates a lookalike site at g00gle.com, the credential for google.com simply won’t work—the origins don’t match, and the authenticator won’t produce a valid signature.
This isn’t a UI warning users can click through. It’s enforced cryptographically at the protocol level.
Discover how at OpenReplay.com.
Synced vs. Device-Bound Passkeys
Modern passkeys typically sync across devices through OS keychains—Apple’s iCloud Keychain, Google Password Manager, or third-party managers like 1Password. This dramatically improves usability since users don’t lose access when switching phones.
Device-bound passkeys (like hardware security keys) offer stronger guarantees—the private key provably exists on exactly one device. For most web applications, synced passkeys provide sufficient security with better UX. Your threat model determines which matters more.
Modern UX Patterns: Conditional UI
You’ve likely seen passkey prompts appear in the username field’s autofill suggestions. This is conditional UI—the browser proactively offers available passkeys before the user explicitly requests passwordless login.
Implement this by calling navigator.credentials.get() with mediation: 'conditional' and adding autocomplete="username" to your input field.
The browser handles discovery and presentation.
Many applications now use conditional UI to upgrade existing users: after a successful password login, prompt users to register a passkey for future sessions.
Security Properties and Trust Boundaries
Passkeys dramatically reduce attack surface, but they’re not magic. The private key’s security depends on the authenticator’s implementation—typically the device’s secure enclave or TPM. If the device itself is compromised at the hardware level, all bets are off.
Account recovery remains a design challenge. When users lose all their devices, you need fallback mechanisms that don’t reintroduce the vulnerabilities passkeys eliminated.
WebAuthn continues evolving—Level 3 is the current generation of the specification—with ongoing work on cross-device authentication and enterprise attestation. The fundamentals covered here remain stable.
Conclusion
Passkeys shift authentication from “verify the user knows a secret” to “verify the user possesses a key.” This changes your mental model: you’re not checking passwords against hashes, you’re verifying cryptographic signatures against public keys.
For frontend engineers, the practical implication is straightforward: learn the WebAuthn API’s registration and authentication ceremonies, implement conditional UI for seamless discovery, and design upgrade paths that move users from passwords to passkeys incrementally.
FAQs
Account recovery becomes critical when users lose all devices. Common approaches include backup recovery codes generated during registration, secondary authentication methods like verified email, or identity verification processes. The challenge is designing fallbacks that do not reintroduce the vulnerabilities passkeys eliminated, such as phishable magic links or interceptable SMS codes.
Yes, passkeys are designed for cross-platform compatibility. Synced passkeys stored in platform keychains like iCloud Keychain or Google Password Manager work across devices within that ecosystem. For cross-ecosystem authentication, users can scan QR codes to authenticate using a passkey stored on a different device, leveraging the FIDO2 hybrid transport protocol.
Each passkey credential is unique and tied to a specific user account and relying party. When multiple passkeys exist for the same domain, the browser or authenticator presents a selection interface letting users choose which credential to use. The credential ID stored server-side maps each passkey to its corresponding user account.
Passkeys resist man-in-the-middle attacks through origin binding. The authenticator includes the exact origin in the signed authentication response. If an attacker intercepts and relays the authentication attempt through a proxy, the origin mismatch causes signature verification to fail. The cryptographic binding makes real-time phishing attacks ineffective.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.