Support conditional passkey creation - #68194
Open
rolandVi wants to merge 2 commits into
Open
Conversation
Contributor
|
Thanks for your PR, @rolandVi. Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
API proposal tracked by #68192.
A Blazor Identity app can now create a passkey for someone silently, right after they sign in with a password, so they get moved off passwords without seeing a prompt or having to find a button. Today a passkey only appears if the user goes looking for the "add a passkey" page, which almost nobody does.
Example usage
Why the server needs telling
This needs new public API because the server cannot work it out for itself. Mediation is not in
clientDataJSON, so it cannot be inferred, and taking it from the client at attestation time would let anyone switch off the user-presence check. It is supplied when the options are made and rides along in the data-protected attestation state.Design notes
Two checks get relaxed. The spec's registration steps skip the user-presence check when mediation is conditional, and the client is required to report both presence and verification as false. Separately,
UserVerificationRequirementis downgraded from"required"to"preferred"in the generated options, because the browser refuses the ceremony outright if a conditional create asks for verification, so without that downgrade nothing reaches the server to verify.I used a bool overload rather than an options object because an options object is source-breaking here: it makes existing
new() { ... }call sites ambiguous. Details in the proposal.SupportsConditionalCreationis there so an app with a customIPasskeyHandlercan ask before calling instead of getting an exception on every sign-in.Template changes
The Blazor template sends the user through a short
/Account/PasskeyUpgradepage after a completed sign-in, which does the creation and then continues to wherever they were headed. It is a separate page rather than something inline on the login page because navigating away cancels the login page's in-flight conditionalget(), which the browser wants aborted before a conditional create starts.The options are created in the sign-in handler itself, on the password, two-factor and recovery-code paths, and carried to the upgrade page in protected TempData. The upgrade page has no code that can issue options: reached without them, it redirects and does nothing. That keeps the decision to relax the registration checks with the code that just checked a credential, rather than with any request carrying a session cookie. It gives up after 5 seconds, and any failure is logged and swallowed, since the user never asked for this and should not see it fail.
Adding a passkey with only a session cookie is wider than this page. #66865 tracks the same weakness on the existing passkey management page and is not addressed here.
Testing
Unit tests cover the verification downgrade, the flag round-tripping through the attestation state, a conditional create succeeding with both flags false, an ordinary create still rejecting a missing user-presence flag, and the
NotSupportedExceptionfrom the default interface method.The template E2E test stubs
getClientCapabilitiesand interceptsnavigator.credentials.create, recording the mediation it was called with. It checks a conditional create is attempted after a password sign-in, after two-factor and after a recovery code, that none is attempted at the two-factor prompt itself, and that navigating straight to/Account/PasskeyUpgradewith a session cookie attempts nothing. The interception means the E2E does not exercise attestation for a conditional create; the server side is covered by the unit testsResolves #67298.