-
Notifications
You must be signed in to change notification settings - Fork 178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
non-modal "conditionally mediated" UI #1576
non-modal "conditionally mediated" UI #1576
Conversation
Update the WebAuthn Conditional UI API to match the proposed specification, replacing the conditionalPublicKey attribute with a "conditional" mediation value. Attempting to set the mediation to "conditional" for password or federated credentials will result in a NotSupportedError. Setting the value for WebAuthn requests will be ignored unless the WebAuthenticationConditionalUI flag is enabled. PR spec: w3c/webauthn#1576 Design doc: https://docs.google.com/document/d/1KzEWP0aoLMZ0asfw6d3-7UHJ6csTtxLA478EgptCvkk Bug: 1171985 Change-Id: Ia0045d7fd9becadeadaa362b29ddd56dc38a79b2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2780274 Reviewed-by: Martin Kreichgauer <martinkr@google.com> Commit-Queue: Nina Satragno <nsatragno@chromium.org> Cr-Commit-Position: refs/heads/master@{#866725}
index.bs
Outdated
exactly one of those, it then calls <code>PublicKeyCredential.{{PublicKeyCredential/[[DiscoverFromExternalSource]]()}}</code> to have the user select a [=credential source=]. | ||
|
||
In any case, the user agent SHOULD show some UI to the user to guide them in selecting and | ||
authorizing an authenticator with which to complete the operation. [=[RPS]=] can provide a hint that a prominent, modal UI <em>should not</em> be used for this process by setting <code>|options|.{{CredentialRequestOptions/mediation}}</code> to "conditional". This is known as a <dfn>Conditional UI Flow</dfn>. [=[RP]=] script SHOULD first check that <code>navigator.credentials.{{CredentialsContainer/conditionalMediationSupported}}</code> is [TRUE] in order to avoid the possiblity of causing a user-visible error to be returned if the user agent does not support [=conditional UI flow=]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just caught myself up on this proposal. On the whole I think this is a great idea. However I suggest we consider the following alternative to the naming of the boolean conditionalMediationSupported
:
navigator.credentials.isConditionalMediationAvailable()
I suggest this because we already have the existing helper method isUserVerifyingPlatformAuthenticatorAvailable()
that establishes an is...Available()
naming convention for these kinds of helper methods. I'm also suggesting this becomes a method instead of a boolean because I believe it will eliminate confusion over whether a particular feature check in the WebAuthn API is a simple boolean, or something that needs to be invoked. If they're all invoked methods that return booleans then there's less mental overhead for RP developers working with this API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @MasterKale, looks like this feedback belongs also in w3c/webappsec-credential-management#155 which is what would add that attribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the nudge, I went ahead and cross-posted. Honestly I feel like this suggestion is less compelling over there without something like isUserVerifyingPlatformAuthenticatorAvailable()
in the credential management API (which there isn't)...
If conditional mediation goes through with conditionalMediationSupported
, is there any value in trying to update PublicKeyCredential
with a new static method isConditionalMediationAvailable()
that returns the value of navigator.credentials.conditionalMediationSupported
? 😛
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A drive-by thought: Is it certain that this kind of support will always be a single boolean? The function leaves open the possibility of arguments in the future, in case the level of support depends on certain properties (e.g. of the registration parameters) in a non-trivial way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ISTM @MasterKale makes good suggestions wrt naming and it being a method rather than a simple boolean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with the arguments for making it a method, but I think the argument should be "public-key"
rather than "publicKey"
, because "public-key"
is the value defined in PublicKeyCredentialType
and returned in PublicKeyCredential
responses. The publicKey
property name in PublicKeyCredential{Creation,Request}Options
should arguably have also been "public-key"
in order to be formally compatible with the Credential Management API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
publicKey
property name inPublicKeyCredential{Creation,Request}Options
should arguably have also been"public-key"
in order to be formally compatible with the Credential Management API.
Indeed, please see w3c/webappsec-credential-management#147 ( which is on the fairly near-term to-do list.. )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm aiming for consistency, so if WebAuthn and CredMan APIs can sync up on "public-key"
then that'd be great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay so -- what about
PublicKeyCredential.isConditionalMediationAvailable()
- works for different credential types in the future!
- very similar to
isUserVerifyingPlatformAuthenticatorAvailable()
! - don't have to worry about the whole
public-key
vspublicKey
thing that still hasn't been resolved!
I need to make a bunch more changes here but I'm very happy with the way feature discovery is tenatively spec'd right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emlun, @MasterKale (and other reviewers!):
WRT @nsatragno's #1576 (comment) immediately above regarding isConditionalMediationAvailable()
being usable by devs as simply PublicKeyCredential.isConditionalMediationAvailable()
, please also see the current state of w3c/webappsec-credential-management#155 -- We're feeling it is getting very close to being baked.
Have the password autofill wait for username if a form field is annotated as `autofill="webauthn"` and the WebAuthenticationConditionalUI flag is enabled. This is the first part of an integration between WebAuthn Conditional UI and password autofill. PR spec: w3c/webauthn#1576 Design doc: https://docs.google.com/document/d/1KzEWP0aoLMZ0asfw6d3-7UHJ6csTtxLA478EgptCvkk Bug: 1171985 Change-Id: I4c9879e36fc3923555731da8f7bf4a957e080e71 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3107526 Commit-Queue: Nina Satragno <nsatragno@chromium.org> Reviewed-by: Vasilii Sukhanov <vasilii@chromium.org> Cr-Commit-Position: refs/heads/main@{#914458}
Integrate the WebAuthn Conditional UI mode with the password manager autofill prompt. When generating suggestions for the autofill popup dialog, have the browser inject a priori discoverable credentials that are eligible to fulfill an ongoing request. If an error occurs during a request, it is not aborted. Instead, the request is silently restarted so the credentials remain a valid option if the user interacts with the input field again. This is a first, rough version for the integration without proper i18n support and pending UX review. This feature is gated behind the WebAuthenticationConditionalUI flag. PR spec: w3c/webauthn#1576 Screenshot: https://screenshot.googleplex.com/Ajp5vePhXrN4sZP Design doc: https://docs.google.com/document/d/1KzEWP0aoLMZ0asfw6d3-7UHJ6csTtxLA478EgptCvkk Bug: 1171985 Change-Id: I40e05f386b23dfcd7fed40519c72669d11aab70b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3140504 Commit-Queue: Nina Satragno <nsatragno@chromium.org> Reviewed-by: Mohamed Amir Yosef <mamir@chromium.org> Reviewed-by: Martin Kreichgauer <martinkr@google.com> Cr-Commit-Position: refs/heads/main@{#924407}
ceefdde
to
f4d48c2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @nsatragno, here's some high-level comments on the latest commit 2e58c0f, which overall is looking good...
- IIUC we are intending conditional mediation to be applicable to all available authenticators, including available roaming authenticators.
- The user is being prompted from both credman's "request a credential" (step 7.5) and here in [[DiscoverFromExternalSource]]'s step 20's "If conditionalFlow is true and the user interacts with an input form control with a "webauthn" autocomplete autofill hint set," branch?
- To override
Credential
'sisConditionalMediationAvailable()
's default implementation, we define an implementation here, rather than attempt to override it using webidl's "partial interface". See the very last paragraph of section 5.1. PublicKeyCredential Interface: "PublicKeyCredential's interface object inherits Credential's implementation of ... and defines its own implementation of ... " (yeah, it's subtle/obtuse)
Hey @equalsJeffH, thank you for your quick review on my rough draft!
Fixed to be "authenticators supporting credential discovery".
That's already the case for vanilla webauthn! Credman is a little confusing there since the "request a credential" step asks the user to "choose a credential" before even calling [[DiscoverFromExternalSource]]! Credman allows the user to select an "interface object" that represents a kind of credential (WebAuthn being the only one that exists). In reality, that selection never actually happens because A) WebAuthn is not supported in conjunction with other credential types so it's the only available option and B) webauthn credential selection requires some user interaction regardless of the mediation requirement. At least that's my understanding after reading the whole thing several times, I might be wrong!
Done. -- I added a bunch of things that were missing and moved things around. Can you take another look? Thank you! ^_^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @nsatragno, here's some high-level comments on the latest commit 2c09264...
- We do not need to define
isConditionalMediationAvailable()
in this spec (in the way you have it presently) -- unless you wish to move that method from theCredential
interface to thePublicKeyCredential interface
-- because we are defining it as part ofCredential
base class (or whatever the webidl term is) in Credential Management PR #155. Again, to overrideCredential
'sisConditionalMediationAvailable()
's default implementation, we define an implementation here, rather than attempt to override it using webidl's "partial interface". See the very last paragraph of section 5.1. PublicKeyCredential Interface: "PublicKeyCredential's interface object inherits Credential's implementation of ... and defines its own implementation of ... " (yeah, it's subtle/obtuse). E.g., note how WebAuthn overrides[[Store]]
's implementation. Similarly,[[Create]]
and[[DiscoverFromExternalSource]]
in webauthn are overriding their default impls in credman. I can write this if it'd be helpful.
update 2021-10-28 wrt (1): I equalsJeffH am effectively wrong here (apologies!), we can do this as @nsatragno proposes. Credman PR #155 defines isConditionalMediationAvailable()
as a method (on the Credential
interface), and as @nsatragno points out, the WebIDL spec says in 2.2. Interfaces: "Interfaces may specify an interface member that has the same name as one from an inherited interface. Objects that implement the derived interface will expose the member on the derived interface. It is language binding specific whether the overridden member can be accessed on the object." We are assuming that this will work fine for JS's language binding. (@nsatragno to test)
-
The
silentCredentialDiscovery
operation simply gathers discoverable creds per a given RP from an authenticator? If so I'm thinking we can say and spec that more straightforwardly. I have some ideas. -
we ought to be more careful/precise with how we are using credential sources -- i think we are just using some of the items they contain, and "entire" cred sources ought not be passed in-whole to the client platform because technically doing so reveals the cred private key. See also new issue Lookup Credential Source by Credential ID Algorithm returns sensitive data such as the credential private key #1678.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I addressed your comments and rewrote silentCredentialDiscovery
to use a new struct DiscoverableCredentialMetadata
which should alleviate the issue with the private key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @nsatragno -- this is looking pretty good overall, thanks! there's a bunch of detail-level comments mostly having to do with maintaining the spec's alg style and use of the Infra spec. Also a few suggestions for adding context for readers.
index.bs
Outdated
@@ -1947,6 +1973,106 @@ This | |||
{{CredentialsContainer/get()|navigator.credentials.get()}} operation can be aborted by leveraging the {{AbortController}}; | |||
see [[dom#abortcontroller-api-integration]] for detailed instructions. | |||
|
|||
#### <dfn for="PublicKeyCredential" algorithm="Issuing a request to an authenticator">Issuing a request to an authenticator</dfn> #### {#sctn-issuing-request-to-authenticator} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably ought to add more context to this alg's description.
In that vein, "CredentialRequest" is the (sub-)term used for the options passed to it, so we can make this match naming-wise:
#### <dfn for="PublicKeyCredential" algorithm="Issuing a request to an authenticator">Issuing a request to an authenticator</dfn> #### {#sctn-issuing-request-to-authenticator} | |
#### <dfn for="PublicKeyCredential" algorithm="Issuing a credential request to an authenticator">Issuing a Credential Request to an Authenticator</dfn> #### {#sctn-issuing-cred-request-to-authenticator} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest we add an introductory paragraph, e.g. (this is a rough initial draft):
This algorithm encompasses the specific UI context-independent steps necessary for requesting a [=credential=] from a given [=authenticator=], using given {{CredentialRequestOptions}}. It is called by {{PublicKeyCredential/[DiscoverFromExternalSource]}} from various points depending upon whether the present [=authentication ceremony=] is subject to [=user mediation=] (e.g.: {{CredentialMediationRequirement/conditional}} mediation).
( I'm also thinking that this alg actually ought to follow [[DiscoverFromExternalSource]] rather than precede it, because the opening paragraphs of section 5.1.4 serve to introduce [[DiscoverFromExternalSource]] per se )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also thinking that this alg actually ought to follow [[DiscoverFromExternalSource]] rather than precede it, because the opening paragraphs of section 5.1.4 serve to introduce [[DiscoverFromExternalSource]] per se
[[DiscoverFromExternalSource]] calls this algorithm though, so maybe that's an argument to keep the order like this?
I added an introductory paragraph.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[[DiscoverFromExternalSource]] calls this algorithm though, so maybe that's an argument to keep the order like this?
I suppose. I'm just thinking from perspective of reader who reads the section 5.1.4 intro text, which intros [[Get]](options)
, which in turn calls [[DiscoverFromExternalSource]]()
, but then the next subsection ("issuing a cred request to an authnr") is an internal function of the latter. I suppose with all the hyperlinks that it does not matter terribly.
@w3c/webauthn contributors interested in reviewing the credential management side of this patch can do so at w3c/webappsec-credential-management/155. I would also suggest considering joining the webappsec wg since that spec lives under that umbrella. |
@equalsJeffH I believe I've addressed all comments in some way or another, please take another look |
e9ae207
to
98d2b5e
Compare
Since the last review:
This is ready to land from my side |
Hm, on closer inspection... can we actually do this? The function definition in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the detailed review @emlun!
Hm, on closer inspection... can we actually do this? The function definition in Credential returns a raw boolean, so I don't actually think we can override it with a different return type, can we?
I am aware of this, I filed w3c/webappsec-credential-management#199. I was planning to get that change merged into credman after bringing this issue to the wg.
Fixes: ``` FATAL ERROR: Line 2246 isn't indented enough (needs 1 indent) to be valid Markdown: " |savedCredentialIds| and |options|.{{CredentialRequestOptions/publicKey}}." LINE ~2379: No 'dfn' refs found for 'extension ids'. [=extension IDs=] LINE ~4158: Multiple possible 'dfn' local refs for 'type'. Randomly chose one of them; other instances might get a different random choice. [=type=] ``` Co-authored-by: Nina Satragno <nsatragno@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @nsatragno !
Note: @equalsJeffH was a member at the time of the PR, so the IPR flag can be overridden. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
From the call of 2022-06-29: we're happy to merge this once the conflict has been resolved. The IPR bot might object to Jeff, but Wendy or others can override because Wendy is happy that Jeff was a member when he did the work. |
SHA: 8ad9448 Reason: push, by @nsatragno Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Update the WebAuthn Conditional UI API to match the proposed specification, replacing the conditionalPublicKey attribute with a "conditional" mediation value. Attempting to set the mediation to "conditional" for password or federated credentials will result in a NotSupportedError. Setting the value for WebAuthn requests will be ignored unless the WebAuthenticationConditionalUI flag is enabled. PR spec: w3c/webauthn#1576 Design doc: https://docs.google.com/document/d/1KzEWP0aoLMZ0asfw6d3-7UHJ6csTtxLA478EgptCvkk Bug: 1171985 Change-Id: Ia0045d7fd9becadeadaa362b29ddd56dc38a79b2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2780274 Reviewed-by: Martin Kreichgauer <martinkr@google.com> Commit-Queue: Nina Satragno <nsatragno@chromium.org> Cr-Commit-Position: refs/heads/master@{#866725} GitOrigin-RevId: dd63c7ffc1616b8925982859c890ffe3cfa47251
This PR enables a non-modal "conditionally mediated" UI feature for WebAuthn which RPs may utilize to provide a credential selection UI only if the user has a discoverable credential registered with the Relying Party on their authenticator (the latter being the "condition"). The credential is displayed alongside an autofilled username or password input field. This helps RPs solve the "bootstrapping problem" when migrating their user base from traditional username and password to WebAuthn: websites can fire a WebAuthn call while showing their typical username and/or password prompt without worrying about showing a modal dialog error if the device lacks appropriate credentials.
See also: Explainer: WebAuthn Conditional/Hinted UI,
as well as this related Credential Management PR #155 (merged)
fixes #1545
Overview "omnibus" issue: #1637
See also discussion in Issues #1356 #1533 #1568
Preview | Diff