Skip to content

Add WebAuthn Signal API support for passkeys - #68129

Open
rolandVi wants to merge 4 commits into
dotnet:rolandVi/passkey-workfrom
rolandVi:roland/passkey-signals
Open

Add WebAuthn Signal API support for passkeys#68129
rolandVi wants to merge 4 commits into
dotnet:rolandVi/passkey-workfrom
rolandVi:roland/passkey-signals

Conversation

@rolandVi

@rolandVi rolandVi commented Jul 31, 2026

Copy link
Copy Markdown
Member

API proposal in #68165.
When someone deletes a passkey or changes their email, the browser's passkey provider now hears about it, so removed passkeys stop being offered at sign-in and the name shown next to a passkey stays right. Today the provider keeps its own copy and never finds out.

Usage

if (SignInManager.SupportsPasskeySignalOptions)
{
    var json = await SignInManager.MakePasskeySignalOptionsAsync(user, userEntity);
}
const { rpId, userId, allAcceptedCredentialIds, name, displayName } = JSON.parse(json);
await PublicKeyCredential.signalAllAcceptedCredentials?.({ rpId, userId, allAcceptedCredentialIds });
await PublicKeyCredential.signalCurrentUserDetails?.({ rpId, userId, name, displayName });

What changed

The payload is built by IPasskeyHandler<TUser>, so it resolves the RP ID the same way creation and assertion already do and a custom handler stays consistent with the passkeys it issued. SignInManager just delegates, like the other passkey methods. The interface shipped in .NET 10, so the new member is a default interface method that throws, paired with SupportsSignalOptions for callers to check first.

This has to live in the framework because an app can't easily assemble the payload: the user handle isn't the user ID, it's the UTF-8 bytes base64url encoded through the internal BufferSource. Get it wrong and the call silently does nothing.

The Blazor template renders a new <PasskeySignals> component on the manage passkeys page and after an email change. It's a custom element rather than JS interop because those pages are static SSR.

Not included

signalUnknownCredential is not here. It deletes permanently instead of hiding, and sign-in can't yet tell "unknown credential" apart from any other failure, so it needs an API addition first. Tracked in #68128.

Testing

Covered end to end with the CDP virtual authenticator: the signalled credential list has to match what the authenticator actually holds, and empty out after a delete.

Resolves #67299

@rolandVi
rolandVi requested a review from a team as a code owner July 31, 2026 10:16
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Jul 31, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Thanks for your PR, @rolandVi. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

Comment thread src/Identity/Core/src/SignInManager.cs Outdated
@@ -1 +1,2 @@
#nullable enable
virtual Microsoft.AspNetCore.Identity.SignInManager<TUser>.MakePasskeySignalOptionsAsync(TUser! user, Microsoft.AspNetCore.Identity.PasskeyUserEntity! userEntity) -> System.Threading.Tasks.Task<string!>!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you open an API proposal following the API review process? #67299 doesn't have a proposed API in it.

Things I'd want the proposal to settle: whether this belongs on IPasskeyHandler<TUser> rather than SignInManager, whether the returned JSON should be a superset of both signal payloads or something directly passable to each JS call, and whether MakePasskeySignalOptionsAsync is the right name once signalUnknownCredential (#68128) shows up, since that one takes a different payload and gets called before sign-in.

@rolandVi rolandVi Aug 3, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #68165. It covers the mentioned talking points. I will align the design with @rokonec, as he will champion it through API review.

Comment thread src/Identity/Core/src/SignInManager.cs
Comment thread src/Identity/Core/src/SignInManager.cs Outdated
Comment thread src/ProjectTemplates/test/Templates.Blazor.Tests/BlazorTemplateTest.cs Outdated
Comment thread src/Identity/Core/src/SignInManager.cs Outdated
Co-authored-by: Stephen Halter <shalter+msft@microsoft.com>
@rolandVi
rolandVi requested a review from halter73 August 4, 2026 08:42
@rolandVi
rolandVi force-pushed the roland/passkey-signals branch from 22e92f2 to 0f8b457 Compare August 4, 2026 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-identity Includes: Identity and providers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants