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); } }