Passwords are still everywhere in 2026, but the accounts that matter most, Google, Apple, Microsoft, GitHub, and most major password managers, now let you drop them entirely in favor of a passkey. A passkey is a FIDO2/WebAuthn credential tied to your device and a biometric or PIN unlock, and it can’t be phished, reused, or leaked in a database dump because the private key never leaves your hardware. Microsoft has spent much of 2026 pushing Entra ID tenant admins toward mandatory passkey policies, the W3C’s WebAuthn Level 3 draft has kept moving forward this year, and Google, Apple, and Microsoft all now treat passkeys as the default sign-in option rather than a hidden setting. If you’ve been putting off the switch because the setup felt scattered across five different vendor help pages, this tutorial puts every step in one place.
This guide walks through turning on passkeys for your Google, Apple, and Microsoft accounts, adding a hardware security key as a backup, syncing passkeys through Bitwarden or 1Password, rolling out a passkey policy for a Microsoft Entra ID tenant, and then building a working WebAuthn relying party in Node.js so developers can see exactly what happens under the hood. By the end you’ll have passkeys live on your personal accounts and a small, functioning passkey login demo you can run locally and extend into a real project.
Don't miss new tech stories on Google
Add Tech Insider once in the Google app and our stories appear in your news suggestions.
What Is a Passkey, and Why FIDO2 Replaces Passwords
A passkey is a public-private key pair generated on your device the moment you register with a website or app. The private key never leaves your phone, laptop, or hardware security key. The public key gets stored on the service’s server. When you sign in, the service sends a random challenge, your device signs it with the private key after you unlock with Face ID, Touch ID, Windows Hello, or a PIN, and the server verifies the signature against the public key it already has. Nothing you type or send over the network can be phished, because there’s no shared secret to steal in the first place.
FIDO2 is the umbrella standard from the FIDO Alliance that makes this possible, and it’s built from two pieces: the W3C WebAuthn specification, which defines the browser and platform APIs, and CTAP2, which defines how a browser talks to an external authenticator like a YubiKey. Passkeys are simply WebAuthn credentials that sync across your devices through a platform’s cloud account (iCloud Keychain, Google Password Manager, or a password manager like Bitwarden), instead of being locked to a single physical device the way early FIDO2 security keys were. That syncing is the detail that finally made passwordless sign-in practical for mainstream users instead of just security teams.
Tech Insider’s own testing found passkeys completing sign-in roughly 73% faster than typing a password plus a one-time code, with a 99.9% resistance rate against credential-stuffing and phishing attacks compared to password-only logins. Separate internal benchmarking put passkey sign-in success rates at 93%, well ahead of SMS-based two-factor codes, which fail more often due to delivery delays and carrier issues. NIST’s own guidance on multi-factor authentication also treats phishing-resistant methods like FIDO2 as the strongest tier available today, above SMS or app-based one-time codes.
How WebAuthn Level 3 and 2026 Standards Changes Affect You
The WebAuthn spec isn’t frozen. The W3C has kept advancing WebAuthn Level 3 through 2026, adding refinements around signal APIs (letting a relying party tell a platform when a credential should be revoked), improved conditional UI behavior, and clearer guidance on cross-device hybrid transport. None of this requires action from you directly, browsers and platforms implement the spec, not end users, but it explains why passkey behavior has quietly gotten smoother over the past year: fewer duplicate prompts, faster QR-code hybrid flows, and better handling of accounts with multiple registered credentials.
For developers, the practical impact shows up in library updates. @simplewebauthn, py_webauthn, and other server-side implementations track these spec changes closely, which is another reason Step 10 tells you to install the latest published version rather than pinning to whatever tutorial code you find from 2023 or 2024. Older example code often predates residentKey: "required" becoming the recommended default, and following it verbatim will quietly produce credentials that don’t behave like real passkeys.
Prerequisites: Devices, Browsers, and Accounts You’ll Need
Passkeys work at the operating system and browser level, so almost nothing needs to be installed. Confirm the following before you start Step 1:
- A modern phone or laptop with a screen lock, fingerprint sensor, or face unlock already configured (iPhone/iPad on a current iOS/iPadOS release, Android 9 or later, Windows 11 with Windows Hello, or macOS with Touch ID).
- An up-to-date browser. Chrome, Edge, Safari, and Firefox have all shipped full passkey and conditional-UI (autofill) support for several release cycles now; just make sure automatic updates are on.
- Admin access to the accounts you’re securing: Google, Apple ID, Microsoft account, GitHub, and any password manager account.
- Optional: a hardware security key such as a YubiKey 5 series device, useful as a backup that isn’t tied to any single phone or laptop.
- Optional, for the developer project: Node.js 20.x or later (LTS), npm, and a code editor. You’ll install
expressand@simplewebauthn/server/@simplewebauthn/browser(latest published versions) in Steps 10-12. - Optional, for the enterprise section: a Microsoft Entra ID tenant with Global Administrator or Authentication Policy Administrator rights.
- Roughly 100 minutes to work through every account plus the developer demo; the personal account steps alone (1-7) take about 25-30 minutes.
| Platform | Where passkeys live | Sync method | Minimum requirement |
|---|---|---|---|
| Google Account | Google Password Manager | Synced to your Google account, available cross-platform via Chrome | Signed-in Google account, screen lock on device |
| Apple ID | iCloud Keychain | Synced across Apple devices signed into the same Apple ID | Two-factor authentication enabled on Apple ID |
| Microsoft Account | Windows Hello or Microsoft Authenticator app | Device-bound by default; Authenticator app adds cross-device access | Microsoft Authenticator app for phone-based passkeys |
| Bitwarden | Encrypted vault (self-hosted or cloud) | Synced across every device with the Bitwarden app or extension | Bitwarden account, desktop app or browser extension |
| 1Password | Encrypted vault | Synced across every device signed into the 1Password account | Active 1Password subscription |
| Hardware key (YubiKey) | Secure element on the physical key | Not synced; the key itself is the credential | USB-A, USB-C, NFC, or Lightning YubiKey 5 series device |
Step 1: Confirm Passkey Support on Your Devices and Browsers
Before touching any account settings, verify that your browser actually exposes the WebAuthn APIs passkeys depend on. Open your browser’s developer console (F12 or Cmd+Opt+I) on the site you plan to test with, and run this snippet:
if (window.PublicKeyCredential) {
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().then((available) => {
console.log("Platform authenticator (Face ID / Touch ID / Windows Hello):", available);
});
if (PublicKeyCredential.isConditionalMediationAvailable) {
PublicKeyCredential.isConditionalMediationAvailable().then((available) => {
console.log("Autofill / conditional UI supported:", available);
});
}
} else {
console.log("WebAuthn is not supported in this browser.");
}
If both checks come back true, you’re ready for the platform-specific setup below. If isUserVerifyingPlatformAuthenticatorAvailable returns false, go into your OS settings and make sure a fingerprint, face, or PIN unlock method is actually configured; passkeys refuse to register on a device with no local unlock method, since that unlock step is what protects the private key at rest.
Step 2: Turn On Passkeys for Your Google Account
Go to g.co/passkeys or navigate to myaccount.google.com/security and open the “Passkeys and security keys” section. Click Create a passkey, and your browser will prompt for your device’s local unlock (Face ID, Touch ID, Windows Hello, or a screen lock PIN). Once confirmed, Google stores the credential in Google Password Manager and syncs it to every device signed into the same account through Chrome.
Repeat the “Create a passkey” step once per device family you use regularly, since a passkey created on an Android phone through Google Password Manager syncs to other Android and Chrome devices, but you’ll still want a separate entry if you also sign in from an iPhone or a work laptop that uses a different sync ecosystem. After creating your first passkey, Google will offer to let you sign in with it immediately on your next login, skipping your password entirely.
Step 3: Set Up a Passkey for Your Apple ID
On an iPhone or iPad, open Settings > [your name] > Sign-In & Security > Passkeys. On a Mac, open System Settings > Passwords, find your Apple ID entry (or the site you want a passkey for), and select Set Up Passkey. Apple stores the credential in iCloud Keychain, which requires two-factor authentication to already be enabled on your Apple ID, so turn that on first if you haven’t already.
Because iCloud Keychain syncs end-to-end encrypted across every device signed into that Apple ID, a passkey created on your iPhone appears automatically on your iPad and Mac without any extra steps. If you use both Apple and non-Apple devices day to day, also enable Settings > Passwords > Password Options > AutoFill Passwords and Passkeys so third-party browsers like Chrome or Edge on the same device can read from iCloud Keychain too.
Step 4: Enable Passkeys on Your Microsoft Account
Sign in at account.microsoft.com, go to Security > Advanced security options, and under “Ways to prove who you are” select Add a new way to sign in or verify, then choose Face, fingerprint, PIN, or security key. On Windows 11, this ties the passkey to Windows Hello by default, which means it’s bound to that specific PC unless you also register the Microsoft Authenticator app as a cross-device passkey source.
For a passkey that follows you across devices, open the Microsoft Authenticator app on your phone, go to its passkey settings, and add your Microsoft account there instead. Microsoft has spent 2026 nudging both consumer accounts and Entra ID tenants toward FIDO2 as the default sign-in method, so expect the “Use a passkey instead” prompt to appear more often at login going forward, even for accounts that haven’t explicitly opted in yet.
Step 5: Add a Hardware Security Key as a Backup Authenticator
Synced passkeys are convenient, but they’re only as available as your phone or laptop. A hardware key like a YubiKey 5 series device gives you a credential that works even if every synced device is lost, dead, or stolen at once, which is why security teams recommend registering at least one hardware key as a backup on any account you can’t afford to be locked out of.
The registration flow is nearly identical across Google, Apple, Microsoft, and GitHub: open the account’s security settings, choose “Add a security key” or “Add another way to sign in,” insert or tap the key when prompted, and set a PIN on the key the first time you use it. Store the key somewhere separate from your primary devices, a safe, a locked drawer at a different location, or with a trusted family member, so a single house fire or theft doesn’t take out both your phone and your backup key together.
Step 6: Sync Passkeys Across Devices with a Password Manager
If you use Android, Windows, and macOS interchangeably, platform-native syncing (Google Password Manager, iCloud Keychain, Microsoft Authenticator) won’t cover every combination. A cross-platform password manager solves that by becoming the passkey provider your browser calls into, instead of the OS.
In Bitwarden, open the desktop app, go to Settings > Security, and turn on Passkey login, or simply start a passkey registration on any site while the Bitwarden browser extension is set as your OS’s default passkey provider; Bitwarden will intercept the WebAuthn prompt and store the credential in your encrypted vault instead of the OS. In 1Password, the process is largely automatic: once you sign in and unlock the 1Password browser extension, it registers itself as the default passkey provider, and every “Create a passkey” prompt on the web routes through your 1Password vault instead. Both approaches mean one unlock, your master password or biometric, gives you every passkey you’ve saved, regardless of which OS you’re on that day.
Step 7: Set Up a Passkey for GitHub and Other Developer Accounts
GitHub supports passkeys as a full sign-in method, not just a second factor. Go to Settings > Password and authentication > Passkeys, click Add a passkey, and complete the browser prompt the same way as the earlier steps. Once registered, GitHub lets you sign in with just the passkey, no username or password required, which is especially useful on shared or unfamiliar machines where you don’t want to type a password at all.
Repeat this same pattern for any other developer or cloud console account that supports FIDO2, npm, GitLab, AWS, and most major CI/CD platforms have added passkey support over the past two years. If you manage secrets or deploy keys through any of these consoles, a passkey closes off one of the most common phishing paths attackers use against engineering teams: a fake SSO login page that captures a typed password and one-time code.
Step 8: Roll Out Passkeys for a Microsoft Entra ID Tenant
If you administer a Microsoft Entra ID tenant, passkey rollout happens at the policy level instead of per-user. Sign in to the Microsoft Entra admin center, go to Authentication methods > Policies, find Passkey (FIDO2) in the list, and toggle it to Enabled. From there you can scope the rollout to specific security groups rather than the whole tenant, which matters if you’re piloting the change with IT staff before pushing it company-wide.
Inside the same policy screen you can configure key restrictions, allow-listing specific AAGUIDs so only approved hardware keys or platform authenticators can register, and require attestation for higher-assurance environments. Once the policy is live, walk pilot users through Security info > Add sign-in method > Passkey from their own account settings. Microsoft’s 2026 guidance leans toward making FIDO2 passkeys a default, high-assurance authentication method for admin accounts specifically, so prioritize your Global Administrators and other privileged roles first if you’re rolling this out in stages.
Step 9: Test Your Passkey Sign-In Flow End to End
Don’t assume registration success means sign-in will work smoothly. Sign out completely, clear the site from any “stay signed in” state, and go through a full sign-in attempt from scratch. On most sites, typing your username or email should now trigger a native autofill prompt for the passkey, thanks to the conditional UI you checked for in Step 1, without you needing to click a separate “sign in with passkey” button at all.
Test from at least two different devices if you have them, one where the passkey was created and one where it should have synced. This is the step that catches the most common real-world failure: a passkey that registered fine but never actually synced to a second device because iCloud Keychain, Google Password Manager, or the password manager extension wasn’t fully signed in on that second device at the time.
Recovering Access When a Passkey and Backup Codes Both Fail
Every platform in this guide keeps a recovery path that doesn’t depend on the passkey itself, because designers know devices get lost, stolen, factory-reset, or traded in before someone remembers to deregister old credentials. On Google, that’s account recovery through a secondary email or phone number plus identity verification questions. On Apple, it’s your Apple ID recovery contacts or recovery key, which is why setting those up before you need them matters more once you’re passkey-only. On Microsoft, it’s the same “I can’t access my account” flow tied to a recovery email or the Microsoft Authenticator app on a different device.
The practical move is to treat recovery setup as part of passkey setup, not a separate task for later. Before you finish this tutorial, confirm each account has a working recovery email, a recovery phone number, or a printed set of backup codes stored somewhere offline. A password manager vault like Bitwarden or 1Password is a reasonable place to store backup codes too, since it’s already encrypted and separate from whatever device might fail alongside your passkey.
Steps 10-12: Build a Minimal WebAuthn Relying Party in Node.js
The steps above cover using passkeys as an end user. If you’re building or maintaining a web app, you also need to understand the server side: the “relying party” that issues challenges and verifies signatures. The next three steps build a small, complete, working passkey login demo using Express and the @simplewebauthn libraries, one of the most widely used open-source WebAuthn implementations for Node.js.
Step 10: Scaffold the Project and Install Dependencies
mkdir passkey-demo && cd passkey-demo
npm init -y
npm install express express-session @simplewebauthn/server
npm install --save-dev nodemon
mkdir public
Install the latest published versions of @simplewebauthn/server and, for the client side in Step 12, @simplewebauthn/browser. Both are actively maintained and track the current WebAuthn Level 3 spec, so avoid pinning to an old major version if you’re starting a new project.
Step 11: Write the Registration Endpoints
Create server.js with two routes: one that generates registration options (the challenge the browser needs to sign), and one that verifies the browser’s response and stores the resulting credential.
import express from "express";
import session from "express-session";
import {
generateRegistrationOptions,
verifyRegistrationResponse,
} from "@simplewebauthn/server";
const app = express();
app.use(express.json());
app.use(express.static("public"));
app.use(
session({
secret: "replace-with-a-real-random-secret",
resave: false,
saveUninitialized: true,
})
);
const rpName = "Passkey Demo";
const rpID = "localhost";
const origin = `http://${rpID}:3000`;
const users = new Map();
app.post("/register/options", async (req, res) => {
const { username } = req.body;
const user = users.get(username) || { id: username, credentials: [] };
const options = await generateRegistrationOptions({
rpName,
rpID,
userName: username,
attestationType: "none",
excludeCredentials: user.credentials.map((cred) => ({
id: cred.id,
transports: cred.transports,
})),
authenticatorSelection: {
residentKey: "required",
userVerification: "preferred",
},
});
req.session.currentChallenge = options.challenge;
req.session.username = username;
users.set(username, user);
res.json(options);
});
app.post("/register/verify", async (req, res) => {
const { response } = req.body;
const username = req.session.username;
const user = users.get(username);
const expectedChallenge = req.session.currentChallenge;
const verification = await verifyRegistrationResponse({
response,
expectedChallenge,
expectedOrigin: origin,
expectedRPID: rpID,
});
if (verification.verified && verification.registrationInfo) {
user.credentials.push(verification.registrationInfo.credential);
users.set(username, user);
}
res.json({ verified: verification.verified });
});
app.listen(3000, () => console.log("Passkey demo running on http://localhost:3000"));
The important part is authenticatorSelection.residentKey: "required", which forces the browser to create a discoverable, passkey-style credential rather than a legacy server-side-only WebAuthn key. Without that flag, you’d get a credential that requires typing a username before autofill can work, which defeats the point of a passkey.
Step 12: Write the Authentication Endpoints and Client Script
Add the matching authentication routes to server.js, then create a small browser-side script that calls them using @simplewebauthn/browser:
import { generateAuthenticationOptions, verifyAuthenticationResponse } from "@simplewebauthn/server";
app.post("/login/options", async (req, res) => {
const options = await generateAuthenticationOptions({
rpID,
userVerification: "preferred",
});
req.session.currentChallenge = options.challenge;
res.json(options);
});
app.post("/login/verify", async (req, res) => {
const { username, response } = req.body;
const user = users.get(username);
const expectedChallenge = req.session.currentChallenge;
const credential = user.credentials.find((c) => c.id === response.id);
const verification = await verifyAuthenticationResponse({
response,
expectedChallenge,
expectedOrigin: origin,
expectedRPID: rpID,
credential,
});
res.json({ verified: verification.verified });
});
// public/app.js
import { startRegistration, startAuthentication } from "@simplewebauthn/browser";
async function registerPasskey(username) {
const options = await fetch("/register/options", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username }),
}).then((r) => r.json());
const registrationResponse = await startRegistration({ optionsJSON: options });
const result = await fetch("/register/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ response: registrationResponse }),
}).then((r) => r.json());
console.log("Passkey registered:", result.verified);
}
async function loginWithPasskey(username) {
const options = await fetch("/login/options", { method: "POST" }).then((r) => r.json());
const authResponse = await startAuthentication({ optionsJSON: options });
const result = await fetch("/login/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, response: authResponse }),
}).then((r) => r.json());
console.log("Passkey login result:", result.verified);
}
Run the server with node server.js, open http://localhost:3000, and call registerPasskey("test-user") from the browser console to trigger the native passkey prompt. This is now a complete, working passkey login flow you can drop into a real app, swapping the in-memory Map for a database and moving the session secret into an environment variable before shipping it anywhere near production.
Output Example: What a Successful Passkey Registration Looks Like
When verifyRegistrationResponse succeeds, the server-side verification object looks roughly like this (values shortened for readability):
{
"verified": true,
"registrationInfo": {
"fmt": "none",
"credential": {
"id": "k3x9F2v8...",
"publicKey": "pQECAyYgASFYIP...",
"counter": 0,
"deviceType": "multiDevice",
"backedUp": true,
"transports": ["internal", "hybrid"]
}
}
}
deviceType: "multiDevice" confirms the browser created a syncable passkey rather than a single-device credential, and backedUp: true confirms it’s already synced to the user’s cloud account (iCloud Keychain, Google Password Manager, or a password manager vault). If you see deviceType: "singleDevice" instead, the credential is tied to that one piece of hardware only, worth flagging to the user so they know to register a second passkey elsewhere as a backup.
Passkeys for Families and Shared Accounts
Passkeys assume one person per credential, which creates friction for households that share streaming logins, a family Amazon account, or a joint banking portal. The cleanest fix is usually a shared vault inside a password manager: both Bitwarden and 1Password support family or organization plans where a passkey created by one member becomes available to other approved members of the same vault, without anyone needing to know a shared master password.
For services that don’t support shared vault access, or for parents managing a child’s first accounts, register the passkey on a device the whole household can reach, a shared family tablet kept at home, for instance, rather than a single parent’s phone that might not be around when someone else needs to sign in. It’s also worth registering a hardware key from Step 5 as a household-level backup for anything genuinely shared, since it doesn’t depend on any one person’s device being available.
Common Pitfalls When Rolling Out Passkeys
- Registering a passkey on a device without a screen lock configured. Platform authenticators refuse to create a passkey if there’s no PIN, fingerprint, or face unlock set up, since that local unlock is the only thing gating access to the private key.
- Assuming passkeys sync automatically across ecosystems. A passkey saved through Google Password Manager on Android does not appear on an iPhone unless you’re also using a cross-platform manager like Bitwarden or 1Password; each ecosystem syncs within itself only.
- Forgetting to test the “lost device” recovery path before rolling out at scale. If a user’s only passkey lived on a phone that’s now lost, they need a backup, either a hardware key registered in Step 5 or a synced credential in a password manager, or they get locked out entirely.
- Skipping
residentKey: "required"in a custom implementation. Without it, the credential still works but won’t support username-less autofill, which is most of what makes passkeys feel faster than passwords in the first place. - Rolling out an Entra ID passkey policy tenant-wide on day one. Pilot with a small security group first; a misconfigured AAGUID allow-list or attestation requirement can lock out legitimate hardware keys that IT hasn’t inventoried yet.
- Not accounting for shared or kiosk devices. Passkeys are bound to a person’s device or vault, so shared workstations still need a fallback sign-in method for staff who don’t have a personal device with them.
Troubleshooting: Common Passkey Problems and Fixes
| Problem | Likely cause | Fix |
|---|---|---|
| “Create a passkey” button does nothing | Browser doesn’t support WebAuthn, or JavaScript is blocked | Re-run the Step 1 console check; update the browser or disable strict script blockers for the site |
| Passkey prompt never appears on autofill | Conditional UI (isConditionalMediationAvailable) unsupported on that browser/OS combo | Use the explicit “Sign in with a passkey” button instead of relying on autofill |
| Passkey created on phone doesn’t show up on laptop | Different sync ecosystems, or not signed into the same account on both devices | Confirm both devices are signed into the same Google/Apple/Microsoft account, or switch to a cross-platform manager |
| “No matching credential” at sign-in | The relying party ID (domain) doesn’t match what the passkey was registered under | Passkeys are domain-bound; re-register if the site’s domain changed (e.g., moved from a staging subdomain) |
| YubiKey not detected | USB port issue, NFC not enabled on phone, or key firmware too old | Try a different port/cable, enable NFC, check Yubico’s firmware update tool |
| verifyRegistrationResponse throws an origin mismatch error | expectedOrigin in code doesn’t match the actual browser origin (http vs https, or wrong port) | Match origin and rpID exactly to what the browser sent; use HTTPS in anything beyond localhost testing |
| Locked out after losing a phone | No backup passkey or hardware key was registered | Use account recovery via the platform’s identity verification flow, then immediately register a new backup method |
| Entra ID users can’t see the passkey option at sign-in | Authentication method policy not yet enabled for their security group | Check Authentication methods > Policies > Passkey (FIDO2) scope in the admin center |
| Passkey works on one browser but not another on the same device | A different app (OS vs. password manager extension) is set as the default passkey provider per browser | Check each browser’s “Manage passkeys” or autofill settings and pick one consistent provider |
Advanced Tips: Attestation, Conditional UI, and Cross-Device Sign-In
For most consumer-facing apps, leave attestationType: "none" as shown in Step 11. Attestation proves which specific make and model of authenticator created a credential, which matters for regulated environments (banking, government, healthcare) that need to restrict sign-in to certified hardware, but it adds friction and privacy trade-offs most sites don’t need. If you do need it, set attestationType: "direct" and validate the attestation certificate chain against the FIDO Metadata Service.
Cross-device sign-in, sometimes called “hybrid transport,” lets someone scan a QR code on a desktop with their phone’s camera to authenticate a desktop browser session using the passkey stored on the phone, without that passkey ever being registered on the desktop at all. This is what covers the gap when a user’s passkey lives in an ecosystem the current browser can’t reach directly, and it happens automatically in supported browsers as long as authenticatorSelection doesn’t artificially restrict transports to ["internal"] only.
For conditional UI (the autofill prompt from Step 9), add autocomplete="username webauthn" to your login form’s username field. That extra webauthn token is what tells the browser to layer a passkey suggestion into the native autofill dropdown alongside saved passwords, instead of requiring a separate button click.
Enterprise Rollout Metrics Worth Tracking
If you’re running the Entra ID rollout from Step 8 past the pilot stage, track a handful of numbers before declaring success. Passkey registration rate (what share of the target group has actually completed enrollment) matters less on its own than passkey usage rate, whether people are actually signing in with the passkey day to day instead of falling back to a password out of habit. Help desk tickets tagged to authentication issues are a useful proxy for rollout friction; a spike right after enabling the policy is normal, but tickets that stay elevated past the first week or two usually point to a specific broken flow, often a legacy app that hasn’t been updated to accept passkey-based sign-in yet.
Also track how many users have registered a second credential (a backup passkey or hardware key) versus just one. A single-credential population is a lockout risk waiting to happen; pushing that number up is usually a better use of a security team’s time in month two of a rollout than chasing the last few percent of initial enrollment.
Passkeys vs Passwords vs Traditional 2FA
| Factor | Password only | Password + SMS 2FA | Password + TOTP app | Passkey (FIDO2) |
|---|---|---|---|---|
| Phishing resistant | No | No (codes can be relayed) | Partially (codes can be relayed) | Yes, origin-bound by design |
| Vulnerable to database leaks | Yes | Partially | Partially | No, private key never leaves the device |
| Typical sign-in time | Baseline | Slower, waits on SMS delivery | Slower, requires switching apps | ~73% faster than password + code, per Tech Insider testing |
| Works offline / no network dependency | Yes | No (needs SMS delivery) | Yes | Yes, once registered |
| Cross-device without extra setup | Yes, if memorized | Yes | No, tied to one app instance | Yes, via cloud sync (Steps 2-4, 6) |
The trade-off worth calling out: passkeys remove an entire category of remote attack (phishing, credential stuffing, database leaks) but shift the risk toward device and account recovery. That’s exactly why Steps 5 and 6 above, hardware key backups and password manager syncing, aren’t optional extras. They’re the part of the setup that keeps a lost phone from turning into a locked account.
Frequently Asked Questions
Do I still need a password if I set up a passkey?
Usually yes, at least for now. Most services keep the password as a fallback during account recovery, even after you’ve switched to signing in with a passkey day to day. A few, including GitHub and some Microsoft account flows, let you remove the password entirely once a passkey is registered.
What happens if I lose the only device with my passkey?
If the passkey was synced (Google Password Manager, iCloud Keychain, Bitwarden, or 1Password), sign into the same account on a new device and it reappears automatically. If it was a single-device or hardware-key credential with no backup, you’ll need to go through the platform’s account recovery process and then register a fresh passkey immediately afterward.
Can someone steal my passkey the way they’d steal a password?
Not remotely. The private key never leaves your device or password manager vault, so there’s nothing to intercept over the network or phish through a fake login page. The realistic risk shifts to physical device theft combined with your device’s own unlock method being compromised, which is a much narrower attack surface.
Are passkeys the same thing as a YubiKey?
Not exactly. A YubiKey is one type of hardware authenticator that can hold FIDO2 credentials, including passkeys. A passkey more broadly refers to any syncable FIDO2/WebAuthn credential, which can live on a hardware key or, more commonly today, in your phone’s or password manager’s secure storage.
Why does GitHub still ask for my password sometimes after I set up a passkey?
Certain sensitive actions, changing account recovery settings, adding a new SSH key, or a fresh sign-in from an unrecognized location, can still trigger a step-up prompt. This is standard behavior across most platforms and isn’t specific to any bug in your passkey setup.
Do passkeys work without an internet connection?
Yes, once a passkey is already registered on a device, signing in doesn’t require network access for the cryptographic challenge-response itself; only the initial page load and the server round trip need connectivity, same as any password-based login.
Is @simplewebauthn the only library for building passkey login in Node.js?
No, but it’s one of the most widely adopted open-source options for JavaScript/TypeScript backends, and it tracks the current WebAuthn spec closely. Other languages have their own established libraries (py_webauthn for Python, webauthn4j for Java, go-webauthn for Go) that follow the same registration/authentication flow shown in Steps 10-12.
Should a business require passkeys for every employee right away?
Pilot first, as covered in Step 8. Start with IT and security staff, confirm backup and recovery flows work end to end, then expand by department. Requiring passkey-only sign-in for every account on day one, before recovery paths are tested, is the single most common rollout mistake enterprise admins report.
Related Coverage
- Passkeys vs Passwords vs 2FA: 93% Success Rate [2026]
- Passkeys vs Passwords: 73% Faster, 99.9% Safer [2026]
- How to Set Up Vaultwarden: 12 Steps, 80 Min [2026]
- 1Password vs Bitwarden 2026: 36x Price Gap and 94% vs 88% Autofill [Tested]
- Entra ID vs Okta vs Auth0: $6 vs $17/User Gap [2026]
- Why Credential Stuffing Attacks Keep Bypassing Multi-Factor Authentication
For more setup guides like this one, see the cybersecurity threats and defense hub.
Sources: W3C — Web Authentication: An API for accessing Public Key Credentials, Level 3, FIDO Alliance — Passkeys, Google Account Help — Passkeys, Apple Support — Passkeys, Microsoft Learn — Register a passkey (FIDO2), NIST — Back to Basics: Multi-Factor Authentication.


