Skip to Content

Passkeys in .NET 10: A Subtle Interop Issue with 1Password (and How We Fixed It)


With .NET 10, ASP.NET Core Identity introduces support for WebAuthN Passkeys. It’s a big step forward for passwordless authentication, although standards implemented by various vendors can lead to interoperability issues even with slight misinterpretations. The latest one I discovered was while preparing for a demo showing off Passkeys with 1Password.

While implementing Passkey authentication, I ran into an unexpected issue when using credentials stored in 1Password, particularly those created via QR code flows on mobile.

The Problem

Most of the time, for demos, I have used Apple Keychain to store Passkeys, but this time I wanted to show that the Passkey registration QR code displayed on my desktop could be scanned by my phone to have the Passkey residing on my phone. My phone is set up to use 1Password for Passkeys, so it stores the Passkey there, not in Apple Keychain. Registration completed successfully, and my public key was registered on the server. However, when attempting to authenticate using the QR code scanned by my phone, authentication failed, and I received the following server-side error, 

“The assertion credential JSON had an invalid format… missing required properties including: 'clientExtensionResults'.”

This all points to a server-side deserialization issue; theclientExtensionResults property is missing from the credential payload generated by the WebAuthN API in the browser. In most cases, this is empty and not used in the core Passkey authentication process. However, the .NET JSON serializer used by the .NET 10 Passkey implementation requires it to be present, even if empty.  When using a physical store or Apple Keychain, this property is present and empty and not a problem, but for 1Password, it is missing, which causes the .NET JSON serializer to break.

Not A Simple Fix

I first tried to simply add the missing property to the credential object returned from WebAuthN before calling JSON.stringify(). However, it turns out that the object returned from the call navigator.credentials.get is not a regular JavaScript object, and adding properties to the returned object will not be visible to JSON.stringify. So that didn't work.

The Adopted Solution

I moved to a DTO-based approach on the client and explicitly constructed the payload, by mapping the various parts from the credential object returned from WebAuthN into a new object that would always meet the requirements of the JSON serializer.

Why This Works

This solution works by taking control of the serialisation and not relying on each WebAuthN authentication provider to provide a response acceptable by the .NET 10 Passkey implementation. So while this is not as simple as calling JSON.stringify, it gives you more confidence that whatever WebAuthN authenticator your users are using, they will be able to authenticate and save you from those strange support calls.

Key takeaways:-

  • Ensures all required properties are present
  • Produces base64url-encoded values expected by ASP.NET
  • Avoids relying on browser object serialization quirks

Alternatively, Fix It Server-Side?

We briefly considered patching the JSON server-side, but rejected it because it would put more burden on the server to handle this edge case. It felt more scalable to make each browser instance format the payload to an acceptable format before sending it to the Passkey authentication API.

Fixing the payload at the source felt cleaner and scales.

Closing Thoughts

This is a great example of how multiple vendors interpret standards can expose subtle interoperability issues.

If you’re implementing passkeys in .NET 10, it’s worth validating your payloads early, against a variety of WebAuthN authenticators, especially if you expect users to rely on tools like 1Password.

Have you hit similar issues with passkeys or WebAuthn? I’d be interested to hear how others are handling cross-platform quirks.

Last updated: 03 May 2026

Andrew is the Managing Director at Rock Solid Knowledge.