v136 · miscellaneous
Passkey Compatibility Matrix
Conditional create() requires the right browser, OS, authenticator, and user state to fire silently. This matrix shows exactly which combinations support automatic passkey upgrades in Chrome 136, plus a profile checker that predicts whether credentials.create({mediation: "conditional"}) would upgrade or skip for a given device profile.
checking WebAuthn…
checking conditional create…
Chrome 136 adds
mediation: "conditional" to navigator.credentials.create(). The browser silently creates a passkey when the user fills a saved password from the password manager — no modal UI unless the platform can't do it silently. Requires: Chrome 136+, platform authenticator (TPM/Secure Enclave), and a password manager suggestion event.
Browser × OS × authenticator compatibility
| Browser | Windows (TPM) | macOS (Touch ID) | iOS/iPadOS | Android | Linux |
|---|---|---|---|---|---|
| Chrome 136+ | ✓ Yes | ✓ Yes | ~ Partial | ✓ Yes | ✗ No |
| Chrome <136 | ✗ No | ✗ No | ✗ No | ✗ No | ✗ No |
| Safari 17+ | ✗ N/A | ~ Partial | ~ Partial | ✗ N/A | ✗ N/A |
| Firefox | ✗ No | ✗ No | ✗ No | ✗ No | ✗ No |
| Edge 136+ | ✓ Yes | ✗ N/A | ✗ N/A | ✗ N/A | ✗ N/A |
Upgrade profile checker
Click "Check upgrade".
Implementation pattern
// Fire AFTER a password autofill event
// The browser silently creates a passkey if conditions are met
async function tryPasskeyUpgrade(userId, userName) {
if (!window.PublicKeyCredential) return;
// Check if conditional create is available
const available = await PublicKeyCredential
.isConditionalMediationAvailable?.();
if (!available) return;
try {
const credential = await navigator.credentials.create({
publicKey: {
challenge: crypto.getRandomValues(new Uint8Array(32)),
rp: { id: location.hostname, name: 'My App' },
user: {
id: new TextEncoder().encode(userId),
name: userName,
displayName: userName,
},
pubKeyCredParams: [
{ type: 'public-key', alg: -7 }, // ES256
{ type: 'public-key', alg: -257 }, // RS256
],
authenticatorSelection: {
residentKey: 'required',
userVerification: 'preferred',
},
// Chrome 136: mediation: "conditional" = no modal unless needed
mediation: 'conditional',
},
});
// Passkey silently created — save to server
await savePasskeyToServer(credential);
} catch (e) {
// NotAllowedError: user declined / not available — silently ignore
if (e.name !== 'NotAllowedError') console.error(e);
}
}