LmCast :: Stay tuned in

Understanding WebAuthn credential protection policy

Recorded: May 24, 2026, 8:58 p.m.

Original Summarized

Understanding WebAuthn credential protection policy

Understanding WebAuthn credential protection policy

This post assumes you're already familiar with the basics of
WebAuthn.

When creating a WebAuthn credential, you can specify whether it should be
discoverable using the residentKey option.

const credential = await navigator.credentials.create({
publicKey: {
authenticatorSelection: {
residentKey: "required",
// ...
},
// ...
},
});

However, the relying party cannot control when or how the credential can be
discovered. You may want it to become discoverable only after user
verification and hide the account’s existence from snooping users. This can
be especially important for security keys, where unlike devices or password
managers that usually require initial authentication, physical possession
alone is often sufficient to reveal registered credentials. To address this,
the CTAP 2.1 specification defines a new credential protection extension,
available through the credentialProtectionPolicy extension
input. CTAP is the specification that defines how platforms
(devices/browsers) and roaming authenticators (security keys) interact.

const credential = await navigator.credentials.create({
publicKey: {
extensions: {
credentialProtectionPolicy: "userVerificationRequired",
enforceCredentialProtectionPolicy: true,
},
// ...
},
});

If the default value userVerificationOptional is used, the
credential can be discovered and used without user verification. If
userVerificationOptionalWithCredentialIDList is used, the
credential cannot be discovered without user verification, but it can still
be discovered and used without user verification if the credential ID is
provided by the relying party. This matches the security of non-discoverable
credentials. Finally, userVerificationRequired indicates that
the credential cannot be discovered or used without user verification.

It’s important to highlight that the extension controls credential discovery
within the authenticator. It is still up to the relying party to verify
whether the assertion was made with user verification if they require it.

The related enforceCredentialProtectionPolicy extension input
configures what should happen if the authenticator does not support
credential protection policy. If set to true, the operation
will fail if it cannot create a credential at the specified security level.
Note that if you use a non-roaming authenticator that does not support
credentialProtectionPolicy but the browser does, the request
will be rejected. As such, this should only be set to true if
you want to allow roaming authenticators.

As for browser support for the extension inputs, Chrome and Firefox support
them, while Safari does not and will simply ignore them.

Browsers can also silently apply a default value if the relying party does
not specify one, which is specifically the case in Chrome.

If residentKey is preferred or
required, Chrome uses
userVerificationOptionalWithCredentialIDList. As noted, this
helps prevent someone with physical access to the authenticator from seeing
which accounts are registered on it.

If residentKey is required and
userVerification is preferred, Chrome will use
userVerificationRequired instead. The confusing part is that
this is not related to credential discovery, but rather serves as a safety
measure to enforce user verification. Chrome assumes the credential is
likely to be used as a single authentication step, since
preferred is commonly used even for passkey authentication.
However, because user verification is still optional and it is up to the
relying party to check for it, if the server does not properly enforce user
verification during authentication, someone could sign in as the user with
only physical access to the authenticator.

The specific behavior is documented in the
Chromium documentation.

The management of WebAuthn credential protection policy extends the control over when and how a credential can be discovered, particularly addressing security concerns related to physical access to authenticators. This control is defined through the credentialProtectionPolicy extension input, which is part of the CTAP 2.1 specification governing interactions between platforms, browsers, and roaming authenticators such as security keys.

When creating a WebAuthn credential, the residentKey option allows specifying discoverability, but the relying party cannot entirely dictate the timing or method of discovery. To enhance security, the credentialProtectionPolicy extension allows defining specific policies regarding discovery. The available values for this policy dictate the level of user verification required for credential discovery. If the default value userVerificationOptional is used, the credential can be discovered and utilized without any user verification. Conversely, using userVerificationOptionalWithCredentialIDList prevents discovery without user verification, but permits discovery if the relying party provides the credential ID. This aligns with the security of non-discoverable credentials. The most restrictive setting is userVerificationRequired, which mandates that the credential cannot be discovered or used unless explicit user verification has occurred. It is crucial to note that while this extension controls discovery within the authenticator, the relying party retains the responsibility to verify whether the subsequent assertion was made with the required user verification.

The enforceCredentialProtectionPolicy extension input governs the behavior when an authenticator lacks support for the credential protection policy. Setting this to true ensures that the operation will fail if the authenticator cannot create a credential at the specified security level. However, this setting should generally only be enabled if allowing roaming authenticators is desired, as setting it to true can cause the request to be rejected if a non-roaming authenticator, which does not support the policy, is used, even if the browser supports it. Browser support for these extension inputs varies; Chrome and Firefox support them, whereas Safari ignores them. Browsers can also silently apply default values if the relying party omits specification, a behavior explicitly noted in Chrome.

Chrome applies specific logic based on the interaction between residentKey and user verification preferences. If residentKey is preferred or required, Chrome utilizes userVerificationOptionalWithCredentialIDList to mitigate the risk of physical access revealing registered accounts. If residentKey is required and user verification is preferred, Chrome defaults to userVerificationRequired. Although this outcome is not directly related to credential discovery, it serves as a mechanism to enforce user verification as a necessary safety measure. Chrome assumes that the credential is frequently used for a single authentication step, especially in contexts like passkey authentication, where the preference for optional verification is common. Nonetheless, because user verification remains optional, the reliance party must implement proper enforcement during the authentication process to prevent unauthorized access based solely on physical possession of the authenticator. The specific operational details of these behaviors are further documented in the Chromium documentation.