Skip to content
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

Support Filtering by allow list in Conditional UI #1793

Closed
ChadKillingsworth opened this issue Sep 5, 2022 · 24 comments · Fixed by #1810
Closed

Support Filtering by allow list in Conditional UI #1793

ChadKillingsworth opened this issue Sep 5, 2022 · 24 comments · Fixed by #1810

Comments

@ChadKillingsworth
Copy link

Description

It is common for sites to re-confirm an already authenticated user's password to perform sensitive operations in an application - such as changing a username, two-factor auth setting or any other security related data point. Replacing this flow with user verifying authenticator credentials is required to fully eliminate password use.

As I worked on implementing Conditional UI, I realized that while the confirming credentials can only be for the currently authenticated user, Conditional UI provides no way to filter those credentials. Choosing the credentials of any user except the currently authenticated one will always fail.

Screenshot 2022-09-05 at 8 31 21 AM

While the Conditional UI explainer explicitly requires an empty allowCredentials list, it seems like this use case was not considered. In traditional password based flows, a hidden field with the username is utilized to hint to password managers which credential is being requested.

Conditional UI needs a method to filter or at least hint which user's credentials are acceptable for this use case.

Related Links

Without a Conditional UI hint, implementers will be forced to rely on some sort of browser state to prevent a negative user interaction which will incur all of the original problems leading to the development of the Conditional UI: #1356

@emlun
Copy link
Member

emlun commented Sep 5, 2022

If the scenario is that you already know the user's identity and their eligible credential IDs, what is the reason you cannot use the modal UI variant?

@ChadKillingsworth
Copy link
Author

ChadKillingsworth commented Sep 5, 2022

I can (and do) offer a button to manually trigger the modal variant of the UI with a provided allowCredentials list to filter to the correct IDs.

Screenshot 2022-09-05 at 9 15 33 AM

However it requires either:

  • The user to know they have a credential and use the button to start the flow
  • Keeping some sort of browser state to know that the user logged in with webauthn credentials and can therefore show the correct flow automatically.

As we have been testing the flow internally, the autofill box has a much higher discovery rate for users and is strongly preferred.

@Firstyear
Copy link
Contributor

We should be clear it filters on user-id not the displayname.

I think it seems niche at first, but this use case will be important in many applications so I think it's good to support.

@lgarron
Copy link
Contributor

lgarron commented Sep 7, 2022

For what it's worth, github.com has a "sudo mode" where this would be handy. https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/sudo-mode

We currently have an experimental feature to prompt for WebAuthn devices (security key or passkey) when the prompt loads, but we've been reluctant to enable that feature for all users. Since our goal is to make passkeys convenient and intuitive for all users, a feature like this could be nice — we would be able to rely on the "conditional" feature instead of having to explain to users what the WebAuthn prompt is and why it might instantly fail. Specifically, this could avoid a user reaction of "why did you even give me a button to show that prompt, if I can't actually use it?"

@emlun
Copy link
Member

emlun commented Sep 7, 2022

Ah - it wasn't clear to me what would be the risk if you already know that this particular user definitely has credentials registered, and thus is likely familiar with WebAuthn. But it seems the concern is that all of their credentials might be (non-synced) platform credentials on different machines than the current one?

@ve7jtb
Copy link
Contributor

ve7jtb commented Sep 7, 2022

Wouldn't supporting the current credentialID allowlist pattern in Conditional UI be simpler than trying to add a filter on user-id?

@timcappalli
Copy link
Member

I don't think the Autofill UI is the right pattern for the the step up use case. You generally don't show the user a username field to ask them to step up. The Autofill UI is designed to address initial sign in.

@ChadKillingsworth
Copy link
Author

ChadKillingsworth commented Sep 7, 2022

But it seems the concern is that all of their credentials might be (non-synced) platform credentials on different machines than the current one?

Yes. In general, the implementors (including myself) are very leery of launching the modal UI flow unless their is a near-guarantee that the user has a valid credential available. Since the spec is specifically written to prohibit this level of advance knowledge it makes it difficult to funnel users to the superior webauthn flows vs traditional passwords.

Wouldn't supporting the current credentialID allowlist pattern in Conditional UI be simpler than trying to add a filter on user-id?

Yes that would definitely solve the issue. I almost wrote that into the initial post, but didn't want to focus the issue solely on that solution.

I don't think the Autofill UI is the right pattern for the the step up use case. You generally don't show the user a username field to ask them to step up. The Autofill UI is designed to address initial sign in.

I'm not sure that is accurate. The webauthn Conditional UI autofill token is valid on both a username or a password input field. Conditional UI was designed to work around the privacy concerns of exposing to the user agent the existence of credentials in advance and the poor UI experience otherwise encountered by simply proactively launching the modal flow.

@timcappalli
Copy link
Member

timcappalli commented Sep 7, 2022

edit: I was convinced on the WG call that this is a good idea. Disregard :)

@Firstyear
Copy link
Contributor

Yeah, since we are already authenticated as this specific user id, and we want re-authentication, we can use the user-id to filter credentials on the client rather than listing all user-ids and their credentials that match the rp id since a non-matching user-id would never succeed in this context.

@ChadKillingsworth
Copy link
Author

There is another related use case as well: for systems where the username and password fields are on separate steps, it is a bit odd for the password autofill to list all usernames. It is the same basic consideration as the step-up auth scenario, but in this case the user is not yet authenticated.

Also in the separate steps scenario, using a credential from a different username does work (at least on my systems), but it seems like something that should be addressed.

In both cases, filtering by username (or even a allowCredentials list) works. On the un-authenticated version though, the username enumeration privacy considerations become applicable if allowCredentials is utilized for the filtering.

@MasterKale
Copy link
Contributor

I've been out on vacation so I've only just now had a chance to read through this.

There is another related use case as well: for systems where the username and password fields are on separate steps, it is a bit odd for the password autofill to list all usernames. It is the same basic consideration as the step-up auth scenario, but in this case the user is not yet authenticated.

This resonates with Cisco specifically as we allow customers to use WebAuthn for SSO, but only after a username has been submitted to check if that user is authorized to use WebAuthn. If we could trigger Conditional UI after that authorization check to only prompt for credentials for the that approved user ID then we'd have so much more freedom to implement Conditional UI.

@timcappalli
Copy link
Member

for systems where the username and password fields are on separate steps, it is a bit odd for the password autofill to list all usernames.

Why wouldn't the user select their passkey in step 1 / screen 1? In theory, you would only show the password field if the user did not select an existing passkey from the username field.

@MasterKale
Copy link
Contributor

Why wouldn't the user select their passkey in step 1 / screen 1? In theory, you would only show the password field if the user did not select an existing passkey from the username field.

For example, Single Sign-On policy doesn't allow use of WebAuthn because the administrator doesn't want to use it. You can't know that till you know a user to check policy for, so prompting for passkey on Step 1 wouldn't be prudent.

@ChadKillingsworth
Copy link
Author

ChadKillingsworth commented Sep 8, 2022

Why wouldn't the user select their passkey in step 1 / screen 1?

I have 2 more cases:

  1. In scenarios with "remembered username" functionality, the login form will pre-select the username.
  2. In the US banking industry, it's common for the username entry to be a form on the marketing web site as step 1 which submits to the online banking service provider (my company). The password entry as step 2 is the first place where I have direct control to add the webauthn flows. It will take years to get all of the marketing sites converted into an iframe embed that supports webauthn.

@timcappalli
Copy link
Member

Why wouldn't the user select their passkey in step 1 / screen 1? In theory, you would only show the password field if the user did not select an existing passkey from the username field.

For example, Single Sign-On policy doesn't allow use of WebAuthn because the administrator doesn't want to use it. You can't know that till you know a user to check policy for, so prompting for passkey on Step 1 wouldn't be prudent.

If that is the policy for that user, then the user wouldn't have a WebAuthn credential for that site, so they'd enter their username.

@timcappalli
Copy link
Member

timcappalli commented Sep 8, 2022

Why wouldn't the user select their passkey in step 1 / screen 1?

I have 2 more cases:

  1. In scenarios with "remembered username" functionality, the login form will pre-select the username.
  2. In the US banking industry, it's common for the username entry to be a form on the marketing web site as step 1 which submits to the online banking service provider (my company). The password entry as step 2 is the first place where I have direct control to add the webauthn flows. It will take years to get all of the marketing sites converted into an iframe embed that supports webauthn.

I'd love to understand number two better. Can you point me to a few live examples, either here or offline/DM?

@MasterKale
Copy link
Contributor

If that is the policy for that user, then the user wouldn't have a WebAuthn credential for that site, so they'd enter their username.

This ignores the very real scenario of a system administrator temporarily enabling use of WebAuthn for a few of their users while trialing a new WebAuthn-powered feature of their SSO subscription before then disabling the feature.

During this trial a user would indeed create a credential and use it for authentication as a participant in the trial. For whatever reason the admin then turns it off (they're done testing, don't like it, etc...), then their users should not still be able to use WebAuthn to log in. This is the purpose of the policy check, so that the SSO provider doesn't prompt for WebAuthn when it shouldn't even if the user has a credential for the site.

@christiaanbrand
Copy link

Wouldn't it make more sense to just send an explicit "Get" request with all the credentialIds that the server knows for this particular user?

Or, alternatively, send the credentialId that the user used to start this particular session? Is there a particular reason for even having the password field there, if we know this user has a passkey (which they potentially even used to initiate this session).

It seems like a better UX pattern to not offer the password field at all if we know the user has a passkey, right? Especially since the goal over time is to get rid of passwords completely.

@MasterKale
Copy link
Contributor

MasterKale commented Sep 8, 2022

It seems like a better UX pattern to not offer the password field at all if we know the user has a passkey, right? Especially since the goal over time is to get rid of passwords completely.

To date Conditional UI doesn't appear to require the <form> to include both a username and password, just at least one input with the "webauthn" value in the <input>'s autocomplete attribute.

I don't think we should get hung up, here in this issue in particular, on whether it's appropriate to show a password input if we're encouraging RP's to go passwordless, since this same filtering issue would exist in a login prompt consisting of a single username field that must be submitted before a password field may be shown (or WebAuthn launched, second factor code sent out, etc...), as is commonly the case in SSO-backed authentications.

Edit: I found the relevant section in the L3 draft of how Conditional UI is defined with respect to the shape of the <form> attempting to enable Conditional UI (https://w3c.github.io/webauthn/#GetAssn-ConditionalMediation-Interact-FormControl):

If options.mediation is conditional and the user interacts with an input or textarea form control with an autocomplete attribute whose value contains a "webauthn" autofill detail token,

So far the spec isn't signalling that a password field must also be present for Conditional UI to be triggered.

@Firstyear
Copy link
Contributor

To date Conditional UI doesn't appear to require the <form> to include both a username and password, just at least one input with the "webauthn" value in the <input>'s autocomplete attribute.

This is a good point, but it's not made very clear on the conditional ui examples I've seen :)

Still I think this is getting a bit derailed, but if we focus on the use case of "we already know the user id must be X and we are re-authenticating" then limiting condition UI by user id is an excellent improvement to UX in this case. That use case alone is enough justification IMO.

@ChadKillingsworth
Copy link
Author

  1. In the US banking industry, it's common for the username entry to be a form on the marketing web site as step 1 which submits to the online banking service provider (my company). The password entry as step 2 is the first place where I have direct control to add the webauthn flows. It will take years to get all of the marketing sites converted into an iframe embed that supports webauthn.

I'd love to understand number two better. Can you point me to a few live examples, either here or offline/DM?

@timcappalli I can discuss this publicly and it will make a good real world use case. The following sites are all demo sites and do not represent real financial institutions. The do however demonstrate an extremely common pattern. I can send you many many real world examples privately if needed. For reference, my company is one of the 3 major financial service providers in the US providing banking service software to US financial institutions. This same scenario is common to the other 2 major providers as well.

Marketing Site
https://www.garden-fi.com/ - this is the "homepage" for the bank. See the "Sign In" link in the top right. You can try out any made up username to see how the flow works. Most banks want users to visit that homepage to get access to online banking as it allows them opportunities to communicate to the customer. They are allowed to submit the username, but not the password. This is is frequently maintained by a different party than the online banking platform.

Screenshot 2022-09-09 at 5 56 17 AM

Online Banking
https://digital.garden-fi.com/ - this is a single platform supporting hundreds of financial institutions and millions of customers. Each institution gets a fully branded experience. This is the site authoritative for login credentials.

Screenshot 2022-09-09 at 5 56 37 AM

You'll notice that on the online banking page that I have direct control of, the username is already determined. In an ideal UX, I would know that the user has a valid credential available and immediately launch the modal flow (this is what our native mobile apps do). Since that is not possible, the Conditional UI autofill (not yet in production) provides a really great experience and accomplishes most of the same goal.

@nsatragno
Copy link
Member

It seems to me there are very valid use cases, and the reasoning to restrict conditional ui to only empty allow credentials was weak. Let's update the spec to allow passing an allowList (hehe) and use it to filter the list.

Whether we think the UX makes sense or not should be up to the website developers.

@nsatragno
Copy link
Member

From the TPAC discussion: note that while there is agreement on letting RPs put credential ids on the allowList, this does not mean non-discoverable credentials will become available on conditional ui. We'll have to word the spec accordingly.

@nsatragno nsatragno changed the title Support Filtering by Username in Conditional UI Support Filtering by allow list in Conditional UI Sep 19, 2022
nsatragno added a commit to nsatragno/webauthn that referenced this issue Sep 30, 2022
Allow filtering credentials during conditional requests by passing an
allowList to navigator.credentials.get. This allows relying parties who
know who the user attempting to authenticate is (e.g. because they
entered their username) to have autofill only show credentials for that
user. See the bug for a description of use-cases.

Fixes w3c#1793
@nsatragno nsatragno self-assigned this Oct 5, 2022
nsatragno added a commit to nsatragno/webauthn that referenced this issue Oct 7, 2022
Allow filtering credentials during conditional requests by passing an
allowList to navigator.credentials.get. This allows relying parties who
know who the user attempting to authenticate is (e.g. because they
entered their username) to have autofill only show credentials for that
user. See the bug for a description of use-cases.

Fixes w3c#1793
nsatragno added a commit that referenced this issue Oct 7, 2022
Allow filtering credentials during conditional requests by passing an
allowList to navigator.credentials.get. This allows relying parties who
know who the user attempting to authenticate is (e.g. because they
entered their username) to have autofill only show credentials for that
user. See the bug for a description of use-cases.

Fixes #1793
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants