w3c / webauthn

Web Authentication: An API for accessing Public Key Credentials
https://w3c.github.io/webauthn/
Other
1.19k stars 179 forks source link

Support a "create or get [or replace]" credential re-association operation #1568

Open lgarron opened 3 years ago

lgarron commented 3 years ago

Proposal

I would like to propose the addition of a way for an RP ask the browser to:

In essence: "create or get", where "or" has the same meaning as in most programming languages (take the second branch if the first was unsuccessful). This could be implemented as:

Note that there are situations where the site is trying to ensure that they end up with a credential that matches certain criteria (e.g. discoverable credential, or platform authenticator) but does not know exactly which existing registrations match those criteria (i.e. if the RP cannot tell because some of those registrations were created with different selection criteria). In this case, it's valuable for the selection criteria to filter the get-style prompt.

(Perhaps "get or create" might make more sense, or maybe it could be useful to give the RP the choice of preference between the operations. In any case, the overall idea is similar.)


Motivation

I originally asked about this #1533 and I felt like it was closed quickly because this was an intentional omission of the spec. However, after a lot of work on GitHub's WebAuthn implementation, and several dozen emails with browser authors, it seems that there is still a fundamental issue with authenticators that are shared across multiple browser profiles (as is the case with Windows Hello):

Note that:

This puts a wrench in certain hacky workarounds, like using a different user handle for each browser session (which not only seems contrary to the intention of the user handle, but can result in a ballooning set of redundant registrations if discoverable credentials are created).

It can also cause issues with sites that have existing registrations for security keys, and want them to keep working while adding support for passwordless flows: https://github.com/w3c/webauthn/issues/1569


I'd argue that the benefits of a "create or get" operation like this outweigh the complexity or security implications. It would allow RPs to:

To me, it seems that this would support the priority of constituencies better than only supporting create or get in the spec.

(EDIT: I flipped the "get" and "create" order after reading @equalsJeffH's comment at https://github.com/w3c/webauthn/issues/1567#issuecomment-777017977 , since most sites would probably prefer the get path over creating additional credentials..)

lgarron commented 3 years ago

create/get/replace

In the main comment I've only mentioned "create or get". The issue title also includes "replace".

GitHub is in a situation where we've been encouraging users to register platform authenticators as security keys. Since it is impossible to tell if an existing registration (or new registration where the RP did not require a platform authenticator) is for a platform authenticator, we don't know which security keys can be used as platform authenticators.

Because of the current behaviour of Windows Hello and Safari, we need to avoid registering a platform authenticator as both a security key and a trusted device.

So we need a flow where a user can "create or get" a trusted device, but also needs to remove a security key registration if it needs to be re-registered as a user-verifying platform authenticator. In that case, it would be useful to:

However, I recognize that this is somewhat more complicated. We would also not need it for GitHub if the spec could guarantee that new credentials will only invalidate existing credentials (i.e. only overwrite the [RP, user handle] key in the credential store) that the RP created without specifying a required/preferred resident key at the time.

EDIT: I've filed https://github.com/w3c/webauthn/issues/1569 to see if it's worth tackling the Windows Hello/Safari behaviour.

Kieun commented 3 years ago

As far as I know, there are no browsers that currently allow users to manage registrations. All the registrations remain forever.

For this, in case of Chrome (maybe Edge as well), you can manage security keys. chrome://settings/securityKeys But I'm not sure how much of users know this settings when they are using security keys.

I'm agree with this concerns when deploying WebAuthn to large number of customers. If the WebAuthn is mature, the browsers behave same and users are well educated, we can go with username-less flow with resident key no matter of the authenticator attachment. E.g., RP just presents a button saying "authenticate with trusted device". If there is a user session or similar one, RP might leverage that hint for better usability.

At this stage, RP might try to go with password-less flow by asking username first (if there is no hint on the browser side) and then prompt authentication with credential Ids. Depending on the authentication response, RP might ask further authentication factor to meet their security requirements. But, if the RP's ultimate goal is username-less flow, RPs should decide the policy whether they allow non-resident key, non-user-verifying security key from the beginning, although these authenticators eventually are now allowed at some point.

akshayku commented 3 years ago

The problem is around the existing platforms which are going to be there for a long time. Also, intention during credential creation should be create it if such a credential for that user does not exist. If a credential exist, InvalidStateError seems like a perfect response to the caller. RP should give all the credentialID to the authenticator during authentication if it is following with-username flows.

equalsJeffH commented 3 years ago

this may be realted to issue #1545 "add support for non-modal UI"

equalsJeffH commented 3 years ago

on 2021-02-10 call: map to L3. noted that a underlying motivation for this is the present lack of Android support for discoverable creds.

lgarron commented 3 years ago

on 2021-02-10 call: map to L3. noted that a underlying motivation for this is the present lack of Android support for discoverable creds.

I'd like to clarify that this is mostly orthogonal, as far as I'm concerned.

The main issue here is figuring out how to ensure that a new browser profile can get an associated registration for an RP while keeping the process as straightforward as possible for the user (i.e. by handling it all in a single prompt, if possible). Until something like #1545 becomes available, there is no way for the RPs to do anything without potential situations where a prompt is guaranteed to lead to an error even in the "happy path".

This is already an issue for authenticators/browsers that support discoverable credentials (notably, Safari and Windows Hello). Discoverable credentials in Android would be very welcome, but would not directly help with this issue.

I realized recently that a potential point of confusion is that we want GitHub to support UVPA trusted devices for users without "normal 2FA". My comment here might help clarify some things: https://github.com/w3c/webauthn/issues/1566#issuecomment-782444786

eldanb commented 3 years ago

Pointing out that the need for "get or create" becomes even more critical with platforms now starting to support platform authenticators that are synchronized between devices (eg Apple's announcements in WWDC21) as well as more and more platforms supporting cross-browser platform authenticators and/or native app authenticators shared with browsers (e.g iOS 14.5).

Many RPs are bringing this up as a barrier to adopting a platform-authenticator, username-less flow.

A "get or create" operation could also offer to the user, in one prompt, to either choose an existing credential or register a new one. (so this can happen without more elaborate credential selection predicates)

emlun commented 3 years ago

Would it be reasonable if RPs could silently check for "does the user have some discoverable credential for this site"? So not allowing the RP to probe for any particular credential IDs (that would enable de-anonymization attacks), but just the presence of some credential they could use? Or would that be too invasive?

eldanb commented 3 years ago

That would definitely answer the RP's requirement described here; but I guess it does compromise privacy more than a "create or get" action.

equalsJeffH commented 3 years ago

The RP techniques and webauthn API changes proposed in issue #1637 will (we hope) ameliorate the concerns expressed in this issue.

kevvurs commented 2 years ago

This issue is essential for iOS 16 Passkeys to work with WebAuthN. Using the platform authenticator on iOS 16, I can setup a passkey on a website like https://webauthn.io for example, and then go to Settings app > Passwords and delete the passkey. Then if you try to login at the same site, it should follow WebAuthN spec for requesting the client to sign a challenge with the private-key. However, when the iOS passkey is no longer accessible, iOS will fall-back on the new "hybrid" flow, which is the QR code feature they recently debuted.

This is very bad because the RP has no way of knowing that the previously registered credential is inaccessible, and when asked for a credential that is not-present, Safari will now display cross-platform options, e.g. transports "usb" and "hybrid" authenticators. The user does not have a clear path to re-register their platform authenticator. Given a create-or-get spec, the RP can recover when a pre-existing credential, especially from the platform authenticator, is no longer available on an iOS client.

timcappalli commented 2 years ago

@kevvurs this sounds like an implementation discussion so I would discuss this issue on the FIDO-DEV list or in the WebAuthn Community Adoption Group. There are no current plans to add an additional method to WebAuthn but there may be other ways to address your concerns.

mitar commented 1 year ago

I was also surprised that this does not already exist. When I heard about passkeys I really though that we finally got to the place where I can just show one "Sign in" button on the site and user can sign in. If user does not have an account, an account is created for them the first time. Similar to how social authentication works, only that the user keeps control through their device/platform or security keys. I also would find this further the privacy of the user: no usernames or even e-mails. Just opaque credential ID. They can provide e-mail maybe for account recovery, but it is not required. Also, browsers could then manage multiple accounts per site and sites would not even have to know about that (again a privacy win).

But currently it seems this is not possible. getOrCreate in my view (in that order) would achieve that for residental keys. I would ask if any key is registered for the site and if not, a new one would be created (of course with user giving consent to the browser to do so). In my view the response could really be PublicKeyCredential with AuthenticatorAttestationResponse or AuthenticatorAssertionResponse, depending if the key was created or just retrieved.

mitar commented 1 year ago

I would also note this SO question which is asking for the same thing.

sameadis commented 10 months ago

Has this issue been resolved or at least has anyone come up with a work around? It's causing a terrible user experience and looks like we can't do anything about it.

rlin1 commented 9 months ago

There are SPC use cases that will benefit from such an option as well.
Today it is an issue that it is not possible to determine whether a WebAuthn credential usable for SPC is available on a device as SPC will show an error message instead of the payment confirmation dialog.