Build the mental model
A password is a shared secret: typed, transmitted, and compared against a stored value. A passkey is a private/public credential pair: nothing secret is typed or transmitted.
| Dimension | How They Compare |
|---|---|
| Phishing resistance | Password can be typed into a fake site and captured. Passkey is bound to the real domain and won't activate on a fake one. |
| What's transmitted | Password sends the secret itself across the network. Passkey sends only a signature, never the secret. |
| Reuse risk | Password can be reused across services, raising risk. Passkey has a distinct key pair per service; reuse isn't even a concept that applies. |
| Ecosystem support | Password support is nearly universal. Passkey support varies by device, OS, browser, and service — not yet universal. |
- Phishing resistance — no secret to type means fake login pages lose their target
- Reduced password reuse — no password means that entire risk category disappears
- Convenience — no memorizing, no typing
Not Universal Yet
Support varies by device, operating system, browser, and service. Expect to use both models side by side for a while.
PASSWORD FLOW vs PASSKEY FLOW
-----------------------------
PASSWORD FLOW vs PASSKEY FLOW
------------------------------
PASSWORD PASSKEY
--------- -------
user types secret service sends challenge
| |
v v
secret TRANSMITTED challenge SIGNED locally
over the network with private credential
| |
v v
server COMPARES it server VERIFIES signature
to stored value using public key only
| |
v v
MATCH -> access SIGNATURE VALID -> access
risk: secret exposed risk: nothing secret
wherever it is typed ever leaves the deviceConnect it to a real scenario
The code below models a login attempt on a suspicious domain, comparing a password-based attempt against a passkey-based one. It's a decision function that only classifies risk, not an attack tool.
- Password on the fake site — theft is possible, the secret transmits with no technical barrier
- Passkey on the same fake site — theft is not possible, domain binding prevents activation entirely
The domain binding isn't a habit you have to remember, it's a property enforced by the credential itself.
Try the working example
function analyzeLoginAttempt({ isPasswordBased, isPasskeyBased, isOnASuspiciousDomain }) {
if (isPasswordBased && isOnASuspiciousDomain) {
return {
credentialTheftPossible: true,
reason: "A password is a shared secret that gets typed and transmitted -- on a fake site, the user unknowingly hands that secret straight to the attacker."
};
}
if (isPasskeyBased && isOnASuspiciousDomain) {
return {
credentialTheftPossible: false,
reason: "A passkey is cryptographically bound to the real site's domain -- on a fake domain it simply will not offer itself for use, so there is nothing to steal."
};
}
if (isPasswordBased) {
return {
credentialTheftPossible: false,
reason: "On the legitimate domain no theft occurs here, but the password remains a shared secret that could still be phished elsewhere or reused."
};
}
return {
credentialTheftPossible: false,
reason: "On the legitimate domain the passkey flow completes normally with nothing secret ever transmitted."
};
}
const passwordOnFakeSite = analyzeLoginAttempt({ isPasswordBased: true, isPasskeyBased: false, isOnASuspiciousDomain: true });
const passkeyOnFakeSite = analyzeLoginAttempt({ isPasswordBased: false, isPasskeyBased: true, isOnASuspiciousDomain: true });
console.log(JSON.stringify({ passwordOnFakeSite, passkeyOnFakeSite }, null, 2));{
"passwordOnFakeSite": {
"credentialTheftPossible": true,
"reason": "A password is a shared secret that gets typed and transmitted -- on a fake site, the user unknowingly hands that secret straight to the attacker."
},
"passkeyOnFakeSite": {
"credentialTheftPossible": false,
"reason": "A passkey is cryptographically bound to the real site's domain -- on a fake domain it simply will not offer itself for use, so there is nothing to steal."
}
}5-minute try-it
Run a password attempt with `isOnASuspiciousDomain: false`. Notice how the reason changes, and think about why it still stops short of calling the password fully "safe" even on the legitimate domain.
One important caution
Assuming passkeys are already available even on services that don't support them yet
Assuming a password used on the legitimate domain is fully free of reuse risk
Quiz: Why Passkeys Resist Phishing
Wikipedia — WebAuthn — Digital Privacy & Modern Security