-
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
Can RPs assume that InvalidStateError
for create()
means an excludeCredentials match?
#1566
Comments
I think Apple's behaviour is a bug. InvalidStateError response from create() means that there exists a credential on the authenticator from the excludelist. cc @alanwaketan |
on 2021-02-10 call: |
Does https://bugs.webkit.org/show_bug.cgi?id=219813 cover it? |
Hey Lucas, Your second point also seems to be laid out in #1568 and thank you for submitting this issue to WebKit 🙇 |
I have to say I'm a bit bewildered by the closing of this issue. Do I understand from the closing of this issue that RPs cannot rely on
Because the time when we need to do this is indistinguishable from a situation where a user is on a new device. It sounds like you're suggesting the following registration for for a new trusted device:
This is undesirable because:
We're currently trying to use heuristics to default to the
Indeed, the authenticator can use the previously created credential if we know to prompt for it. This requires either:
In general, neither makes it possible possible to prompt for the credential in a fresh browser profile until a user already has full authenticated. |
I just realized that there may be an assumption that may lead to miscommunication: whether 2FA is required. Currently, a GitHub user with "normal 2FA enabled" must use the following to sign in:
A user with "normal 2FA disabled":
We intend to start by using trusted devices as described here, to make re-authentication on a device easy. If a user registers or uses a trusted device in a given browser profile, then we we will remember their device in a cookie even after logout, and show them a trusted device login prompt (instead of a password login) when they try to log in next time1. ➡️ But we want to make this feature available to all users, **even those who do not have "normal 2FA enabled"2. ⬅️ This means a GitHub user with "normal 2FA enabled" must use the following to sign in:
A user with "normal 2FA disabled":
It's important that the registration of a trusted device does not turn a "normal 2FA disabled" user into a 2FA user, because we want this feature to be low-friction and only "value added". We don't want to force them to sign up for for "normal 2FA" in order to register a trusted device, and we don't want to require 2FA for all logins as soon as they have a trusted device somewhere. (If that device is a platform authenticator3, they'd be locked out of signing into any other device!). This means that they will only need to provide their password in a fresh browser profile in order to be completely logged in. And since we only prompt them for their password, this means we don't prompt them for their trusted device, and we can't tell if this new browser profile has a trusted device registered, i.e. if they could log in using a trusted device the next time. We could:
We're currently trying to figure out how to deal with the latter. As described above, we need to handle both the case where there is already a trusted device registered for this browser profile (in which a Does that help clarify our concern? P.S. Our password field is directly below the username field as part of the same prompt. We do not intend to change this. Footnotes
|
Far be it that I get in the middle of this thread (and the complexity WebAuthn has spawned), but if there is no intent to implement FIDO for its raison d'etre, why bother implementing it at all? |
I’m not sure I follow. We’re implemented “trusted devices” as described in the spec (see my link above). The trusted device concept works regardless of whether a user has additional 2FA options, and we want to offer something that is both safer and more convenient than what the vast majority of users are currently using. Industry-wide adoption numbers for 2FA are low, and I think that gating trusted device functionality behind the complexity of normal 2FA is counter to the goals and the spirit of the spec. (That said, I think it would be great to get to the point where WebAuthn can be used so commonly that we can raise the bar for non-WebAuthn login as well.) |
It seems that you tries to prompt "platform authenticator" when the user visits sign-in pages and he/she has already registered the "platform authenticator" with that device. My understanding is that RP would rely on some "ambient credential" (with cookie or something) indicating the user registered the platform authenticator in that machine (and browser as well). So, if there is any client side "ambient credential" when the user visits sign-in pages, you can prompt the webauthn authentication (depending on your policy, you may include that user's other credential). In this case you can provide a button for the user to retry the webauthn authentication so that the user might retry or sign in with the password. (since you cannot distinguish "user cancel" and "not available authenticator") If there is no ambient credential, you'd better not asking webauthn authentication (trusted device) in a first place.
That said you need to rely on the "ambient credential" when you prompt the "trusted device" authentication and you should create "ambient credential - hint" on the every browsers (when the user register their platform authenticator or authenticate with platform authenticator). |
Indeed, therein lies the problem — getting a new browser profile into an appropriate "ambient credential" state. Your first few paragraphs pretty much describe our current goals.
Unless I'm misunderstanding, these two are exactly at odds. If we follow step 2 as written, then we are asking the user for authentication at a time when there is no ambient credential. We can try to dress it up a friendly UI, but there is no way to control the browser UI for this, which is designed for authentication. As mentioned before, we'd like to use heuristics to reduce how often this happens, by e.g. skipping straight to your step 3 if we don't think the user has an registered authenticator with the same platform scope (e.g. Windows Hello in any browser/Chrome on macOS/Safari on macOS/Safari on iOS). But our heuristics might be wrong, hence our desire to tell if we guessed wrong, i.e. when the new registration failed because of an existing registration. |
I'm thinking that shared credential for the platform authenticator across browsers is similar concept to roaming authenticator, because the credential can be roaming between browsers. You can guess if you get "InvalidStateError" when you try to create the credential for the platform authenticator. But, you never 100% confirm that the credential can be used for the authentication without asking authentication.
After the user logs in with the password in case of no ambient credential on the browser, you could identify whether the user has registered the platform authenticator before or not. If there is, you could ask WebAuthn authentication w/ allowList (also indicating internal transport as well), then browser will handle that request.
Then, you can explicitly know that the user can authenticate with the platform authenticator on that browser if the authentication is successful. The other thought is that you just simply call create function without the exclude credential. Instead, you might need to use another attribute for ambient credential instead of generated credential id or something. |
Motivation
Suppose that a user has a platform authenticator registered in one browser, and would like to use it in another browser that shares the authenticator (e.g. using Windows Hello in Edge and Chrome). To an RP with a fresh browser session, the "same platform authenticator in a different browser" case is indistinguishable from the "entirely new device" case. But since some platform authenticators make it impossible to have multiple credentials for the same RP, it's important that the RP can re-associate a credential across browsers instead of overwriting an existing one.
The most useful thing for the RP would be a way to query "does a registration already exist?", which I presume is out of the question. (Is it?)
The second-most useful thing would be a way for the RP to "create or get" a credential. However, this was not seen as an area of improvement for the spec when I brought it up. (But I'd be very glad to see it revisited. I don't see a significant privacy issue, and it would avoid the need for the kinds of workarounds that led to me filing this issue.)
As it stands, if a RP does not want to place 100% of the responsibility of keeping track of registrations to their users, they have to ask the user to
create
a new credential and offer a fallback if the user may be trying to register an already-registered credential.It would be nice to minimize the number of choices we offer to the user (i.e. optimistically show only the
create
option), and utilize thecreate
error to provide the most useful feedback and followup actions for the user.InvalidStateError
Based on talking to some browser authors, it seems that the spec is currently designed so that an
InvalidStateError
response fornavigator.credentials.get()
means the registration failed because all authenticators that match the selection criteria (e.g. user-verifying platform authenticator) already have a registration for the RP ID.However, Safari currently has a bug for this situation that makes the "registration already exists" result the same as if the user had canceled the operation: https://bugs.webkit.org/show_bug.cgi?id=219813
In addition, the spec seems to make no guarantees that
InvalidStateError
will only cover this particular meaning in the future. The general meaning ofInvalidStateError
is certainly vague enough to apply in other situations.Would it be possible to clarify whether RPs can rely on this?
We'd like to know whether Apple's implementation should be considered a bug, or if we need to weaken clarity of our platform authenticator (re-)registration flow to accommodate for the possibility that
InvalidStateError
does not indicate an existing registration.The text was updated successfully, but these errors were encountered: