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

Authenticators that do not recognize any handles shouldn't just be dropped on the floor #863

Closed
kpaulh opened this issue Apr 6, 2018 · 22 comments

Comments

@kpaulh
Copy link
Contributor

kpaulh commented Apr 6, 2018

Context from the sister issue raised in the CTAP2 spec: fido-2-specs/issues/509:
"When a privacy-conscious client collects assertions, it does not reveal immediately to an RP that no authenticator recognized any of the identifiers in the allow list. Doing so would allow malicious RPs to test for the presence of authenticators using only a credential id.

In Chrome, both in U2F and WebAuthn, we handle this by making plugged in USB authenticators blink until the user selects one of them (and thereby gives consent to reveal its presence). At that point we return an error indicating that no key handle was recognized."

We had been doing this in the cryptoken extension as well. However, the WebAuthN spec, in 6.2.3.2, states that if no credentials are present on that authenticator,
"return an error code equivalent to "NotAllowedError" and terminate the operation."
(Effectively, drop the device on the floor and waiting for other hotplugged devices.)

To be consistent with CTAP2, we think we should send the authenticator one of the keyhandles so that it blinks, and if the user selects that authenticator by giving it a tap, then return "InvalidStateError" to indicate the user tried to use a device that wasn't actually registered.

(Similar to how the spec handles user consent for already-registered authenticators in 6.2.2.3)

@emlun
Copy link
Member

emlun commented Apr 13, 2018

This issue stands in opposition to issue #867.

update by @equalsJeffH: related to this are user experience (UX) use cases, see issue #334

@emlun
Copy link
Member

emlun commented Apr 13, 2018

I'm not sure this would make for the best user experience. I agree that it's valuable to be able to inform the user that an authenticator doesn't have any applicable credentials, but could that be done by the browser instead of the RP?

In https://bugs.chromium.org/p/chromium/issues/detail?id=828567 you say:

[...] after discovering that an authenticator does not contain any of the credentials in allowCredentials, we send additional winking commands anyways.

If the browser has this knowledge, why not present that to the user directly? As pointed out in #867, it would likely make for a confusing and frustrating user experience if multiple authenticators light up when only one of them can generate a valid response.

I imagine it could look something like this:

  1. RP calls navigator.credentials.get({ ... allowCredentials: [{ id: "foo" }] })
  2. User's device has no a platform authenticator, or foo is not on the platform authenticator
  3. Browser prompts "Please insert your security key."
  4. User plugs in an authenticator that doesn't contain foo
  5. Browser prompts "This security key is not accepted for this authentication, please try a different one." and does not send the command to the authenticator
  6. User plugs in another authenticator that doesn't contain foo (while the first is still connected)
  7. Browser prompts "None of the connected security keys is accepted for this authentication, please try a different one." and does not send the command to the authenticator
  8. User plugs in an authenticator that does contain foo
  9. Browser sends the command to the authenticator and the authentication ceremony proceeds as normal

Would that work?

@equalsJeffH
Copy link
Contributor

equalsJeffH commented Apr 18, 2018

@emlun wrote:

If the browser has this knowledge, why not present that to the user directly?

I wonder whether the browser folk are reticent to directly provide UX of this sort because of the desires for RPs to have fine-grained control over such UX (as has been argued as the reason the UA-provided HTTP authentication dialogs are hardly ever employed) ?

Hm, also, if not the UA handling the UX, the RP's client-side JS could handle all this authnr-selection interaction, without necessarily incurring the latency of comms with the server, yes?

@emlun
Copy link
Member

emlun commented Apr 23, 2018

For the record, I think that consistency with CTAP2 isn't really necessary in this case. CTAP2 specifies a 1-to-1 client-to-authenticator interaction while WebAuthn specifies a 1-to-many client-to-authenticator interaction, so I think it makes sense to handle the case differently on the two levels.

I wonder whether the browser folk are reticent to directly provide UX of this sort because of the desires for RPs to have fine-grained control over such UX [...]

Good point.

My concern with the solution proposed here is how it would interact with combinations of multiple authenticators. Multiple blinking USB dongles is one thing, and likely a minority use case, that might be a little annoying but probably quite harmless - but what about platform authenticators? If this would mean that USB dongles would light up and an OS popup would appear on every authentication even if the platform authenticator isn't eligible, I suspect that might be more disorienting than helpful. All of this is speculation, though - I'd be happy to re-evaluate my position if there are any user studies (of any size) on this.

And then again there's the UX customization issue which could hurt adoption. I don't really feel qualified to tell which is the lesser evil...

@emlun
Copy link
Member

emlun commented Apr 24, 2018

Hm, also, if not the UA handling the UX, the RP's client-side JS could handle all this authnr-selection interaction, without necessarily incurring the latency of comms with the server, yes?

Yes, but what I'm more worried about is friction in the user interaction - having to start the ceremony all over after it seems like you're done, instead of being nudged to plug in a different authenticator.

@kpaulh
Copy link
Contributor Author

kpaulh commented Apr 25, 2018

Sorry for going AWOL, wanted to double-check some facts with folks first before making a bunch of assertions :-)

Jeff largely has it right with regards to not wanting to do all the UX in the browser. It's also difficult to build functioning RPs if we don't respond to certain calls.

If this would mean that USB dongles would light up and an OS popup would appear on every authentication even if the platform authenticator isn't eligible, I suspect that might be more disorienting than helpful.

Regarding platform authenticators, Chrome does intend to have a dialog to notify the user (and not call down to the platform authenticator, so as to prevent OS popups), after which Chrome will return to the RP.

For what it's worth, we have empirical evidence from our rollout of security keys at Google (using the cryptotoken extension) where we got lots of bug reports saying their 'keys didn't work' when in fact they weren't registered. When cryptotoken changed to make them blink, the complaints stopped (rigorous user study, right??).

@emlun
Copy link
Member

emlun commented Apr 25, 2018

rigorous user study, right??

It's definitely better than my pure speculation, at least. 😄

Regarding platform authenticators, Chrome does intend to have a dialog to notify the user (and not call down to the platform authenticator, so as to prevent OS popups), after which Chrome will return to the RP.

I don't quite understand what you mean by that - notify the user about what? In the scenario where a laptop has a platform authenticator built in and navigator.credentials.get() is called with allowCredentials: [{ id: "foo" }], where foo is on a currently disconnected USB key, what would Chrome do?

@kpaulh
Copy link
Contributor Author

kpaulh commented Apr 25, 2018

I don't quite understand what you mean by that - notify the user about what? In the scenario where a laptop has a platform authenticator built in and navigator.credentials.get() is called with allowCredentials: [{ id: "foo" }], where foo is on a currently disconnected USB key, what would Chrome do?

Yeah, I wasn't clear. If
a) the laptop had a platform authenticator and
b) a request was made that required a platform authenticator but
c) allowCredentials didn't have any matching credentials,
Chrome would notify the user that the website is trying to use a credential that is not on the platform, and after dismissing the dialog Chrome would notify the RP of the same.

Otherwise, both RP and user would just sit there for the entire timeout with blank looks of confusion.

@emlun
Copy link
Member

emlun commented Apr 25, 2018

Ok. What I meant to ask was if

a) the laptop had a platform authenticator and
b) a request was made that required any authenticator (platform OR roaming) but
c) allowCredentials didn't have any credentials matching any platform credential,

then what would Chrome do?

@christiaanbrand
Copy link

So, to be honest, today, there's no good way in WebAuthn for an RP to indicate that they "definitely only want to deal with platform authenticators" when doing a "get" (or sign). I believe this might be a bit of a drawback for RPs who really don't want to bother users with external devices, but let's plan on discussing that in more detail in Amsterdam.

Let's assume for a moment the RP has a way to say "I definitely want a platform authenticator" and say so. In that case, Chrome will present a dialog to the user saying "there are no keys here" and then will notify the RP upon dismissal of the box.

If the RP doesn't specify a preference (or says that the key might explicitly be on a roaming authenticator) I think we should tell the user to insert a key.
a) If they happen to insert a key on which the credential resides and touches it: SUCCESS
b) If they happen to insert a key on which the credential doesn't reside: Make it blink. And when the user touches it, tell the RP the credential isn't here.

If the user is confused by the dialog and closes it, tell the RP that there's no credential here.

Does that make sense?

@emlun
Copy link
Member

emlun commented Apr 26, 2018

Yes, that makes sense to me. @kpaulh's assertion about empirical results had me mostly convinced, but I was curious about what the introduction of platform credentials would mean for this.

That said, the 2018-04-25 WG call decided to not take this on until L2. I'm not sure what that means for whether or not Chrome's behaviour as described here will be conformant with the L1 spec.


[...] today, there's no good way in WebAuthn for an RP to indicate that they "definitely only want to deal with platform authenticators" [...] this might be a bit of a drawback for RPs who really don't want to bother users with external devices [...]

My thoughts on this:

  1. There is a way - maybe not a good one, but one that might be functional enough.
  2. I don't see why that should be up to the RP to decide (aside from concerns about confusing users with instructions to insert external devices they don't have).

1: The RP can check isUserVerifyingPlatformAuthenticatorAvailable() and not offer to register a credential if no platform authenticator is available, and also set authenticatorSelection.authenticatorAttachment to "platform" in the create() call. The RP can then know that no user has any roaming credentials.

2: Alternatively, the RP can just do the isUserVerifyingPlatformAuthenticatorAvailable() and not set the authentication attachment parameter. In that case the majority of users would likely register the platform authenticator, and if some users go out of their way to register a roaming authenticator anyway then that's their choice and they're aware they're not doing the primarily supported thing - you could hardly call that "bothering users with external devices", right?

@nadalin
Copy link
Contributor

nadalin commented Mar 7, 2019

@kpaulh to create PR

@emlun
Copy link
Member

emlun commented Mar 13, 2019

Coming back to this...

For what it's worth, we have empirical evidence from our rollout of security keys at Google (using the cryptotoken extension) where we got lots of bug reports saying their 'keys didn't work' when in fact they weren't registered. When cryptotoken changed to make them blink, the complaints stopped (rigorous user study, right??).

I suppose Chrome at that time didn't have a popup telling the user that the connected authenticator isn't registered? Would such a dialog eliminate the need for user action on the authenticator?

@akshayku
Copy link
Contributor

akshayku commented Apr 3, 2019

Yeah, with UI, we probably don't need this.

@equalsJeffH
Copy link
Contributor

shud we punt this to WD-02 ?

@ve7jtb
Copy link
Contributor

ve7jtb commented May 3, 2019

Punt or drop. With a browser dialog I don't think requiring an authenticator touch really makes sense.

@nadalin nadalin modified the milestones: L2-WD-01, L2-WD-02 May 15, 2019
@equalsJeffH
Copy link
Contributor

punt to WD-02

@equalsJeffH equalsJeffH assigned equalsJeffH and unassigned akshayku Jun 12, 2019
@nadalin
Copy link
Contributor

nadalin commented Jun 12, 2019

@equalsJeffH @kpaulh Please review

@kpaulh
Copy link
Contributor Author

kpaulh commented Jul 3, 2019

The issue has been resolved as far as Google and Microsoft are concerned now that Chrome has retry UI.

My only lingering question is how Mozilla plans to handle this case without UI, and if the wording in the spec should allow for both a) UI that tells the user to try a different key or b) in the absence of UI, require a touch before returning anything to the RP.

@jcjones
Copy link
Contributor

jcjones commented Jul 3, 2019

Mozilla will eventually have a similar UI, but that might be a while.

Nevertheless, perhaps this can be closed, then.

@equalsJeffH
Copy link
Contributor

@kpaulh:

UI that tells the user to try a different key...

this would be UI materialized by the client platform, not the RP ?

@kpaulh
Copy link
Contributor Author

kpaulh commented Jul 4, 2019

@equalsJeffH right, UI in the browser that can silently query authenticators without making them blink.

But if J.C. is satisfied for now, I'd say we can close this.

@kpaulh kpaulh closed this as completed Jul 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants