What is a passkey?
A passkey is a sign-in credential built on the FIDO2 standards: W3C Web Authentication (WebAuthn) in the browser and FIDO's CTAP protocol between devices. When a user creates a passkey for a site, their device generates a public/private key pair bound to that site's domain, the relying party ID. The private key stays in the device's secure hardware or in a password manager that syncs it across the user's devices; the site stores only the public key. To sign in, the user unlocks the passkey with a fingerprint, a face scan or the screen-lock PIN, and the device signs a fresh challenge from the server.
That design removes what phishing depends on. There is no password to type into a fake page and no one-time code for a scammer to request over a call or a lookalike WhatsApp chat. The browser offers a passkey only on the domain it was registered for, so a lookalike site receives nothing usable, and because the server holds only public keys, a database breach does not hand out credentials. Synced passkeys survive a lost phone through the user's password manager; device-bound passkeys on hardware security keys never leave the key.
A passkey is one kind of credential, whereas Two-Factor Authentication (2FA) is the broader practice of adding any second factor: an authenticator app, an SMS code, an Authentication Template OTP on WhatsApp, or a passkey. Many apps now combine them: a WhatsApp OTP or Silent Network Authentication (SNA) proves control of the phone number at sign-up or recovery, and a passkey handles every sign-in after that. On Meta's side, WhatsApp has supported passkeys on Android since October 2023 and on iOS since April 2024, and Facebook added passkey sign-in on iOS and Android in June 2025, which matters because Facebook accounts are how admins reach a business portfolio and its WABA.
Key takeaways
- A passkey is a FIDO2/WebAuthn key pair: the private key stays with the user's device or password manager, your server keeps only the public key.
- Passkeys resist phishing because the browser offers them only on the exact domain they were created for.
- There is no shared secret to steal: a server breach leaks public keys, and there is no code for a scammer to ask for.
- Passkeys can replace both the password and the one-time code; WhatsApp or SMS OTPs stay useful for sign-up and recovery.
- WhatsApp has supported passkeys since 2023 and Facebook since June 2025, so admins of a business portfolio can use them too.
Why the difference matters
Why does a passkey matter?
Phished passwords, socially engineered OTPs and codes diverted by SIM Swap Fraud are the main routes to Account Takeover (ATO), both of customer accounts and of the Meta admin accounts that control a business's WhatsApp number. Passkeys close those routes instead of adding friction to them: sign-in becomes a fingerprint, success rates go up, password-reset tickets go down, and fewer one-time codes are sent on every login. For a business paying ₹0.14 per authentication message in India, moving repeat sign-ins to passkeys also trims a recurring cost.
How does a passkey work?
- Step 1
Register the passkey
Your server creates a random challenge, and the browser calls
navigator.credentials.create()with your relying party ID (your domain) and the user's ID. The device creates a key pair and returns the public key and a credential ID. - Step 2
Store the public key
Verify the registration response (challenge, origin, RP ID hash) and save the credential ID, public key and signature counter against the user. Nothing secret is stored on your side.
- Step 3
Challenge at sign-in
When the user returns, the server issues a new single-use challenge and the browser calls
navigator.credentials.get(). The device finds the passkey for your domain and asks the user to unlock it. - Step 4
Verify the signed assertion
The device signs the authenticator data together with a hash of
clientDataJSON, which records the challenge and the origin. Your server checks the signature with the stored public key, plus the origin, the RP ID hash and the user-verified flag. - Step 5
Plan recovery
Let users register more than one passkey and keep a recovery path, such as a WhatsApp or SMS OTP plus extra checks, for when every device is lost.
Common mix-ups
Common mistakes with a passkey
Leaving the password as an easy fallback
If every account still accepts a password plus an SMS code, attackers simply phish that path. Once a user has a passkey, steer sign-in to it and protect fallbacks with stronger checks.
Weak account recovery
A recovery flow that resets everything after one OTP becomes the new phishing target. Require several signals for recovery, notify the user on every channel, and add a delay before high-risk changes.
Choosing the wrong relying party ID
Passkeys are bound to the RP ID. Registering on
www.example.inand later serving login fromapp.example.instrands users' passkeys; use the registrable domain,example.in, from the start.Reusing or predictable challenges
A challenge that can be guessed or is accepted twice lets a captured assertion be replayed. Generate at least 16 random bytes per ceremony, store them server-side with a short expiry and delete them on use.
A passkey in code
// Sign in with a passkey. The server supplies a fresh, single-use challenge.const options = await fetch("/auth/passkey/options").then((r) => r.json());const credential = await navigator.credentials.get({publicKey: {challenge: base64urlToBuffer(options.challenge), // random, expires in minutesrpId: "example.in", // the passkey only works on this domainuserVerification: "required", // fingerprint, face or screen locktimeout: 60000,},});// Send the signed assertion back for verification.await fetch("/auth/passkey/verify", {method: "POST",headers: { "Content-Type": "application/json" },body: JSON.stringify({id: credential.id,clientDataJSON: bufferToBase64url(credential.response.clientDataJSON),authenticatorData: bufferToBase64url(credential.response.authenticatorData),signature: bufferToBase64url(credential.response.signature),}),});
navigator.credentials.get is the standard WebAuthn browser API; base64url helpers are left out for brevity.
A passkey: key facts and limits
- Standards
- FIDO2: W3C WebAuthn + FIDO CTAP
- Your server stores
- Public key, credential ID, sign counter
- Unlocked with
- Fingerprint, face scan or device PIN
- Phishing resistance
- Bound to the relying party ID (domain)
- Kinds
- Synced (password manager) or device-bound (security key)
- Android since Oct 2023, iOS since Apr 2024
- iOS and Android since June 2025
Passkey FAQs
Is a passkey more secure than an OTP?+
What happens to my passkeys if I lose my phone?+
Is a passkey the same as two-factor authentication?+
Can I use a passkey for my Meta business admin account?+
Example: Passkeys for a Hyderabad health-insurance app
A health-insurance app in Hyderabad verified every login with a WhatsApp OTP. Scam calls asking policyholders to "read back the code" led to several hijacked accounts. The team keeps the WhatsApp OTP for sign-up and recovery but prompts users to create a passkey right after their next successful login. Within a quarter most active users sign in with a fingerprint, OTP volume on login falls sharply, and the scam script stops working because there is no code to read out. Recovery still uses an OTP plus a policy-number check, rate-limited against brute force.
Rules of thumb
Best practices for a passkey
- Offer to create a passkey right after a successful OTP sign-in, when the user is already verified.
- List passkeys in account settings with device names and a remove button.
- Turn on passkeys or security keys for every admin of your Meta business portfolio.
- Measure sign-in success rate and OTP volume before and after rollout to show the effect.
* Per-message rates for India, ex-GST: marketing, utility and authentication effective 1 July 2026; service messages ₹0.145 since 1 October 2026 (they were ₹0 until 30 September 2026). Volume commitments earn discounts — final rate is confirmed on your account; applicable GST extra. Rates for other countries differ (see the international rate table on /pricing).