How to Fix Sites Forcing Platform Passkeys (and Get Your QR Code Back)
Trying to set up a passkey on a website, but it skips the QR code and forces you straight into Windows Hello, Touch ID, or Google Password Manager—with no option to use your phone? You’re not imagining it, and it’s not your browser.
Passkeys are a massive step forward for authentication, but poor frontend implementations can turn a seamless experience into an incredibly frustrating one.
If you prefer to keep your passkeys centralized on a roaming authenticator—like your iPhone—you expect to see a QR code when setting one up on a desktop browser. However, you’ve likely encountered sites that completely bypass this option, aggressively locking you into Google Password Manager, Windows Hello, or macOS Touch ID, with no apparent way to choose another device.
The issue isn’t your browser; it’s a rigid, hardcoded constraint in the website’s frontend code. Fortunately, there is a simple way to intercept and bypass it.
The Root Cause: Misusing authenticatorAttachment
When a website initiates the creation of a passkey, it calls the WebAuthn API via navigator.credentials.create(). Within the payload passed to this function, developers can define an authenticatorSelection object.
One of the properties inside this object is authenticatorAttachment. It generally accepts two values:
"cross-platform": Roaming authenticators (like a YubiKey or a phone via QR code)."platform": Built-in authenticators bound to the current device (like Windows Hello, Touch ID, or an integrated browser enclave like Google Password Manager).
If developers want to offer the most objectively effective and flexible user experience, they should either set this to "cross-platform" or simply leave it undefined, allowing the user’s browser to offer all available options.
However, many sites hardcode "platform" into their configuration. When Chrome receives this explicit directive, it honors the API request by immediately locking the UI to its internal Google Password Manager or handing it off to the local OS enclave. The option to use a phone is stripped out entirely because the site specifically demanded a local hardware token.
This isn’t just Big Tech pushing its own ecosystem. The same anti-pattern shows up across regional fintech, brokerages, and marketplaces—places with no incentive to lock you into Google or Apple. The likely culprit is WebAuthn SDK boilerplate: vendor sample code ships with "platform" as the “secure default,” integration teams copy it, and nobody revisits the choice.
The Workaround: Intercept and Strip the Constraint
In the past, Chrome power users could disable the #web-authentication-enclave-authenticator flag to bypass Google’s aggressive UI funneling. Google has since removed this flag, cementing the behavior into the browser core.
Since we can no longer rely on a browser toggle, the most effective solution is to monkey-patch the API call before it reaches the browser engine. By intercepting navigator.credentials.create, we can dynamically sanitize the payload and strip out the offending constraint.
The Fix
When you are on a site that refuses to let you use your phone for passkey creation, follow these steps:
- Refresh the page to start with a clean slate.
- Open your browser’s Developer Tools Console (F12, Ctrl+Shift+J on Windows/Linux, or Cmd+Option+J on macOS).
- Paste the following JavaScript snippet and press Enter:
const originalCreate = navigator.credentials.create;
navigator.credentials.create = function(options) {
// Check if the rigid platform constraint exists in the payload
if (options?.publicKey?.authenticatorSelection?.authenticatorAttachment) {
// Strip the constraint to restore standard browser behavior
delete options.publicKey.authenticatorSelection.authenticatorAttachment;
console.log("Intercepted WebAuthn request and removed authenticatorAttachment constraint.");
}
// Pass the sanitized request to the native API
return originalCreate.call(this, options);
};
- Leave the console open and click the website’s button to create the passkey.
Why This Works
This snippet acts as a middleman. When the site’s script fires its hardcoded WebAuthn request, our function catches it. We navigate the object path (options.publicKey.authenticatorSelection.authenticatorAttachment), delete the restrictive property, and immediately forward the clean payload to the actual browser API.
Without the rigid "platform" directive forcing the use of the local hardware, Chrome behaves as it naturally should. It will pop open the standard WebAuthn dialog, complete with the “Use a different device” option and the QR code needed to store the key on your phone.
A Note on System Design
Protocols like WebAuthn are designed to abstract away complexity while offering maximum flexibility to the user. Hardcoding constraints that artificially limit user choice is an anti-pattern. Until all platforms adopt better API implementations, keeping a simple intercept script handy is the most pragmatic way to maintain control over your own credentials.