Skip to main content
CybersecurityHacking

WebAuthn Integration Breaches Windows RDP Security Gap

Laptop connected to external authenticator device in bright office setting.

“We built the first RDP client outside of Windows to support WebAuthn redirection, beating Microsoft's own macOS, iOS and Linux clients to it (since then FreeRDP has added support too, which we’re happy to see).” — Prisma Browser

What Prisma Browser set out to solve

Prisma Browser engineers set a practical goal: when a user inside a remote desktop session triggers a WebAuthn ceremony (for example, on okta[.]com), the remote server should be able to redirect that ceremony to a local authenticator such as a YubiKey, Touch ID, Windows Hello, or a phone via caBLE/Hybrid. Microsoft documents a mechanism for this in MS-RDPEWA, the “WebAuthn Virtual Channel Extension,” which transmits CBOR-encoded WebAuthn requests over an RDP dynamic virtual channel named Microsoft::Windows::RDP.Webauthn.

The technical roadblock: clientDataJSON vs. clientDataHash

The remote server computes clientDataHash = SHA-256(clientDataJSON) and sends that 32‑byte hash over the RDP channel. Standard browser APIs such as navigator.credentials.create() construct their own clientDataJSON — typically using an origin like chrome-extension://... — and insist on producing and hashing that JSON themselves. The result is a different hash, a signature verification failure on the relying party, and no way for navigator.credentials to accept a pre-computed clientDataHash.

Prisma Browser evaluated alternatives (chrome.webAuthenticationProxy, remoteDesktopClientOverride, WebHID) and found none fit: browsers do not expose an API that accepts a pre-computed clientDataHash, and WebHID is USB-only. They also noted three concrete problems with attempting to reconstruct clientDataJSON locally: browsers may produce different byte encodings/field ordering, native SDKs add variability, and many Windows servers send only the 32‑byte hash with no cleartext origin or challenge.

W3C work is moving in this direction — the remoteClientDataJSON extension (editor's draft section 10.1.6) — but at the time Prisma Browser built their solution no shipping browser supported it.

Reverse-engineering webauthn.dll and mstsc.exe behavior

Prisma Browser found that Microsoft’s Windows implementation of WebAuthn has a “dual personality.” The public API exposed by webauthn.dll (WebAuthNAuthenticatorMakeCredential, etc.) is strict and requires a full clientDataJSON — the path browsers use. Separately, webauthn.dll implements an IWTSPlugin for the WebAuthN_Channel via an exported VirtualChannelGetInstance() entry point. That plugin path is used by mstsc.exe and, crucially, accepts hash-only requests.

To verify actual behavior, the team hooked mstscax.dll with Frida and captured two complete FIDO2 ceremonies. They observed no clientDataJSON on the wire: the server sent only the 32‑byte clientDataHash and the client returned a CTAP2 response. mstsc.exe does not call the public WebAuthn API in this flow. Prisma Browser reverse-engineered the private call chain and identified a private function, CtapCborDecodeRpcRequest, that treats clientDataJSON as optional and will pass through the hash when JSON is absent.

Microsoft documents IWTSPlugin and the VirtualChannelGetInstance prototype (the GUID IID_IWTSPlugin appears in tsvirtualchannels.h), but the documented references do not describe the plugin’s hash-only handling — the very behavior Prisma Browser replicated in their Windows code path.

How Prisma Browser implemented a cross-platform solution

Their engineering stack combined several components:

  • A DVC plugin for the WebAuthN_Channel implemented in C and integrated into their WebAssembly (Wasm) client.
  • A custom Chromium extension API exposing makeCredential() and getAssertion() methods that are identical to navigator.credentials except that callers may supply clientDataHash directly; the extension reuses Chromium’s FIDO2 stack for authenticator discovery (USB, BLE, NFC) and platform authenticators (Touch ID, Windows Hello) and caBLE/Hybrid phone-as-authenticator.
  • A TypeScript protocol layer to handle CBOR encoding/decoding for MS-RDPEWA, including undocumented pieces they encountered when building the feature.

This approach avoids shipping a separate native helper and leverages Chromium’s existing FIDO2 machinery. It works against newer Windows servers that transmit clientDataJSON and against older servers (the majority in many enterprises) that send only the clientDataHash.

What this means for technologists, open-source clients, and standards bodies

Technologists and security teams: if you operate browser-based RDP clients, expect to handle two server behaviors: v9 servers that include clientDataJSON and legacy servers that send only a clientDataHash. Prisma Browser’s work shows one practical path: a custom extension plus a DVC plugin that mirrors mstsc.exe’s private handling.

Open-source implementers and client developers: the protocol MS-RDPEWA is platform-agnostic on the wire, but implementing it correctly has required reverse-engineering mstsc.exe because the spec previously omitted commands and fields. FreeRDP implemented non-Windows support in version 3.25.0 (April 2026), and MS-RDPEWA revision 3.0 (March 2026) documented commands that were previously missing.

Standards bodies and vendors: browser support for a remoteClientDataJSON capability is in progress at the W3C, and Microsoft has updated MS-RDPEWA to document previously undocumented commands. Until browsers accept a pre-computed clientDataHash, third-party clients must either replicate Microsoft’s private behavior or rely on server-side updates.

Prisma Browser’s work demonstrates a clear fact: the wire protocol can be clean and portable, but implementation knowledge — including private behavior buried in webauthn.dll’s DVC plugin — determined whether non-Windows clients could successfully redirect WebAuthn ceremonies. For now, third-party RDP clients that want broad compatibility must bridge both the spec and the private implementation details Microsoft used in mstsc.exe.

Original story: How We Added WebAuthn to a Browser-Based RDP Client