WebAuthn virtual authenticator UV behavior diverges from platform authenticator modalities
0 reputation · 07 Jul 2020, 19:47 UTC
0 reputation · 07 Jul 2020, 19:47 UTC
Chrome's WebAuthn Virtual Authenticator API via CDP enables automated passkey testing without physical security keys. The WebAuthn.addVirtualAuthenticator command creates a virtual authenticator with configurable hasUserVerification and hasResidentKey options.
When hasUserVerification=true and WebAuthn.setUserVerified(true) is called, the virtual authenticator always reports the UV flag as true in assertions. However, it does not enforce platform-specific UV modalities (Windows Hello PIN, Touch ID, Android biometric) or replicate hardware-enforced UV retry limits and lockout behaviors. The User Presence (UP) flag is also always reported as true with no CDP command to toggle it independently.
This creates a gap for relying parties that branch logic on authenticatorAttachment (platform vs cross-platform) or implement UV retry policies. Credential storage remains ephemeral and in-memory, unlike platform authenticators that persist via cloud sync.
33275 reputation · 08 Jul 2020, 01:42 UTC
The WebAuthn Virtual Authenticator API via Chrome DevTools Protocol (CDP) is designed for functional testing, not high-fidelity hardware emulation. The divergence you observe between platform authenticators (like Windows Hello) and virtual authenticators occurs because the latter acts as a simplified state-machine rather than a bridge to the OS-level security modules.
The primary reason the virtual authenticator does not replicate platform-specific UV modalities or retry limits is that it lacks a connection to the Trusted Execution Environment (TEE) or Secure Element. When you call WebAuthn.setUserVerified(true), you are manually flipping the uv flag in the virtual device's internal state. It does not trigger the underlying biometric or PIN logic because there is no hardware-backed interface to invoke.
addVirtualAuthenticator to define specific modalities (e.g., Fingerprint vs. PIN) or to increment a retry-limit counter. The UV state is binary in the context of the virtual authenticator API.toggleUP command.If your relying party logic branches based on authenticatorAttachment or UV status, use the following approach to bridge the gap:
instrument: 'platform' or cross-platform', ensure your test script explicitly sets this to trigger your branching logic.assertionResult response and manually modify the uv boolean to test how your application handles a false state.Note: If you are testing the enforcement of the userVerification: required requirement, ensure your virtual authenticator was created with hasUserVerification: true, otherwise the browser will reject the request.
Use comments to ask for clarification. Post a solution as an answer.
33,275 reputation · 07 Jul 2020, 23:59 UTC
The Chrome CDP virtual authenticator exposes a single hasUserVerification flag. When WebAuthn.setUserVerified(true) is called, the authenticator merely flips the uv bit in the response; it does not invoke any OS‑level biometric or PIN logic. Likewise, the up bit is always set to true once the virtual device is attached, and there is no separate command to toggle User Presence.
Although the WebAuthn Level 3 spec defines an uvRetries extension to surface retry counters, the current Chrome implementation does not expose this extension. Credentials created with the virtual authenticator live only in memory and are not persisted or synced like platform authenticators.