Conversation
...es/content/BlazorWeb-CSharp/BlazorWebCSharp.1/Components/Account/Pages/Manage/Passkeys.razor
Outdated
Show resolved
Hide resolved
|
|
||
| // Immediately prompt the user to enter a name for the credential | ||
| // If the authenticator is known, assign the inferred name and go back to the passkeys list | ||
| if (PasskeyAuthenticators.TryGetDefaultDisplayName(attestationResult.Passkey, out var defaultName)) |
There was a problem hiding this comment.
Should this guard about setting the name if there is already a name set?
There was a problem hiding this comment.
Is the name a default that can be overriden by the user? my question is based on this
- // Immediately prompt the user to enter a name for the credentialThere was a problem hiding this comment.
By user do you mean developer or end user of the web app?
The end user can click the "rename" button in the "Passkeys" page, and they'll be taken directly to the "Rename passkey" page, bypassing this code path.
The developer can change the PasskeyAuthenticators.cs file to make the defaults whatever they want, as it's template code.
Or is the concern that the developer could set the default name in a custom UserManager, so the name would be populated in between passkey creation and the passkey name inference? If so, the current behavior of this code is to overwrite any predefined passkey name with one of the defaults defined in PasskeyAuthenticators, if present. We could change this logic to check that passkey name is empty before replacing it with an inferred one, but that might not always be what the developer wants (maybe they set the default explicitly to "Unnamed", which would disable passkey name inference even when it's probably desirable). I don't have a strong opinion about what the right behavior is here, so I could go either way.
| public static class PasskeyAuthenticators | ||
| { | ||
| private static readonly Dictionary<Guid, string> KnownAuthenticators = new() | ||
| { | ||
| // Google Password Manager | ||
| [new("ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4")] = "Google Password Manager", | ||
|
|
||
| // Apple iCloud Keychain | ||
| [new("fbfc3007-154e-4ecc-8c0b-6e020557d7bd")] = "iCloud Keychain", | ||
| [new("dd4ec289-e01d-41c9-bb89-70fa845d4bf2")] = "iCloud Keychain", | ||
|
|
||
| // Microsoft Windows Hello | ||
| [new("08987058-cadc-4b81-b6e1-30de50dcbe96")] = "Windows Hello", | ||
| [new("9ddd1817-af5a-4672-a2b9-3e3dd95000a9")] = "Windows Hello", | ||
| [new("6028b017-b1d4-4c02-b4b3-afcdafc96bb2")] = "Windows Hello", | ||
|
|
||
| // 1Password | ||
| [new("bada5566-a7aa-401f-bd96-45619a55120d")] = "1Password", | ||
| [new("b5397571-8af2-4d30-9d48-eeb8eee6e9c6")] = "1Password", | ||
|
|
||
| // Bitwarden | ||
| [new("d548826e-79b4-db40-a3d8-11116f7e8349")] = "Bitwarden", | ||
| [new("cc45f64e-52a2-451b-831a-4edd8022a202")] = "Bitwarden", | ||
| }; |
There was a problem hiding this comment.
Would it make sense for this dictionary to be configurable/extensible? I imagine this could be applicable to other managers. I would think something like putting this in Options
There was a problem hiding this comment.
It's already configurable in the sense that it's template code and can be changed arbitrarily by the developer, isn't it?
There was a problem hiding this comment.
Pull request overview
This PR enhances passkey UX by persisting the authenticator AAGUID during attestation and using it in the Blazor Web App template to infer a friendly default passkey display name (reducing the need for a rename prompt).
Changes:
- Add
Aaguid(byte[]?) toUserPasskeyInfoandIdentityPasskeyData, and extract it during passkey attestation. - Update store/test mappings and spec assertions to round-trip the new
Aaguidfield. - Add template logic to map known AAGUIDs to friendly authenticator names and display inferred names + creation date in the passkeys list.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWebCSharp.1/Components/Account/PasskeyAuthenticators.cs | Adds AAGUID→friendly-name mapping and helper methods for display/inference. |
| src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWebCSharp.1/Components/Account/Pages/Manage/Passkeys.razor | Uses inferred display names and creation dates; auto-assigns a name for known authenticators. |
| src/Identity/test/Shared/PocoModel/PocoUserPasskey.cs | Extends test POCO model with an AAGUID field. |
| src/Identity/test/InMemory.Test/InMemoryStore.cs | Maps AAGUID between POCO and UserPasskeyInfo. |
| src/Identity/samples/IdentitySample.PasskeyUI/InMemoryUserStore.cs | Maps AAGUID between POCO and UserPasskeyInfo in sample store. |
| src/Identity/samples/IdentitySample.PasskeyConformance/InMemoryUserStore.cs | Same as above for conformance sample store. |
| src/Identity/Specification.Tests/src/IdentitySpecificationTestBase.cs | Adds AAGUID to passkey equality assertions. |
| src/Identity/Extensions.Stores/src/PublicAPI.Unshipped.txt | Declares new public API surface for IdentityPasskeyData.Aaguid. |
| src/Identity/Extensions.Stores/src/IdentityPasskeyData.cs | Adds persisted Aaguid property. |
| src/Identity/Extensions.Core/src/UserPasskeyInfo.cs | Adds Aaguid property to passkey model. |
| src/Identity/Extensions.Core/src/PublicAPI.Unshipped.txt | Declares new public API surface for UserPasskeyInfo.Aaguid. |
| src/Identity/EntityFrameworkCore/src/IdentityUserPasskeyExtensions.cs | Maps Aaguid between EF entity JSON payload and UserPasskeyInfo. |
| src/Identity/Core/src/PasskeyHandler.cs | Extracts AAGUID from attestation and sets it on the created UserPasskeyInfo. |
Infer passkey display name from AAGUID
Summary
This PR improves the passkey user experience in the Blazor Web App project template by automatically inferring display names for passkeys based on their AAGUID (Authenticator Attestation GUID).
Fixes #63630
Changes
Framework (
Microsoft.AspNetCore.Identity)Aaguidproperty (byte[]?) toUserPasskeyInfoandIdentityPasskeyDatato persist the authenticator's AAGUIDPasskeyHandlerto extract the AAGUID during passkey attestationIdentityPasskeyDatauses a JSON column)Blazor Web App Template
PasskeyAuthenticators.cswhich maps known AAGUIDs to friendly authenticator namesPasskeys.razorto display inferred names and creation dates for each passkeySupported Authenticators
The template includes mappings for the top 5 most commonly used passkey authenticators:
Developers can easily add more authenticators by extending the dictionary in
PasskeyAuthenticators.cs.Demo
Before
passkey_ui_old.mp4
After
passkey_ui_new.mp4