webauthn
webauthn copied to clipboard
Personal information updates & webauthn
This mirrors issue 914 on FIDO (CTAP).
At the moment, there is no straightforward way to update a user's personal information (name
and displayName
) associated to a credential. If a user wants to do it, they have to:
- If the credential is discoverable:
- Have the relying party register a new credential using the same user handle. Note that this requires an implementation from the relying party to always use the same user handle for the same user. I expect many implementations to simply generate a random user handle for each credential and associate that to their actual user identity.
- If the credential is not discoverable:
- Have the relying party register a new credential.
- Have the relying party remove the old credential.
This situation is pretty bad. Users and relying parties might not even be aware of this issue, and it is easy to imagine an account picker with an old name appearing during log-in long after the user has updated their identity to the website.
--
To make this situation better, I propose the following check-list of changes:
-
Add a
authenticatorUpdateCredential
operation on the authenticator model that allows updatingdisplayName
,name
, and any other mutable metadata associated to the user the credential belongs to. -
For stateless credentials, disallow packing
otherUI
into the credential ID.otherUI
might include mutable information such as the user's name. Credential IDs are meant to be immutable and I also see no reason for packing that information anyway since it doesn't seem to be surfaced later. - Add a section under Relying Party Operations detailing the process to update the user information (at the moment it would be a description of the steps above... but maybe we can do better).
-
Provide a better way to update the personal information without user action. One way I can think of is adding a
credentials.get
extension that specifies the new values fordisplayName
/name
for each credential on the allow-list. This would be fairly straightforward to implement but unfortunately wouldn't work for empty allow-lists. Perhaps if the RP uses empty allow-lists, then they could have their users go through a webauthn flow as part of the personal information update. A much more complex idea for platforms but probably better for users would be to provide a hook between returning a credential ID and finishing the webauthn request. Websites would be able to use this hook to query their back-end for personal information updates and have the browsers update that before finishing the request.
See also issue #1200
I never really understood why Webauthn mandates we process the name of a user. Is it actually used by any browsers to even be displayed at the moment?
It us used for discoverable/resident credentials in Windows 10 / Chrome / Safari. They are displayed as part of the credential pick list when no allow list is sent.
Is there any way this could be achieved using store()
? This is how it’s done for other Credential types.
(FWIW: the most challenging thing about this API for me so far has been its unidiomatic nature vis a vis other platform standards and conventions.)
@bathos some of inconsistencies are from the transactional nature of the commands and that there is no guarantee that the 'visible' set of authenticators/keys will be there in-between calls.
For example, attempting to update the username associated with a credential or delete a credential might involve a NFC key which the user does not have with them at the moment, or even that they may be on a machine without NFC capabilities.
Further, non-discoverable credentials do not really exist in an enumerable fashion outside a list of supplied credential handles by an RP, and allowing RP enumeration of the list of available discoverable and non-discoverable credentials is a privacy risk in general. So there is no way to know that many actions could work before initiating them.
My expectation personally is that we see WebAuthn evolve to indicate broader actions, and to have the client (browser/platform) taking on more responsibility to mediate RP requests - the client has persistent state across all RPs and hardware/platform access to communicate with authenticators.
So there is no way to know that many actions could work before initiating them.
I gathered some of that from the thread about why there’s nothing like PublicKeyCredential.supports(opts)
. In this case — and that one — I don’t quite understand why “this is problematic for non-discoverable” would also have to mean “so it can’t be done for discoverable creds, either”. Even if there’s a future where a solution is found for updating or support-checking of non-discoverable creds, is there a problem with throwing for those cases in the mean time, unlocking the capabilities for discoverable creds?
Though the idiosyncrasies I was thinking of weren’t related to that exactly...
- the one-off usage of CBOR without an apparent initiative to make it usable in the language of the API
- "icon" instead of "iconURL" (CredentialUserData), even though they mean the same thing and are part of the same overall API
- abbreviations apparently motivated by byte-shaving instead of intelligibility (e.g. "rp" instead of "relyingParty")
- broadly, underabstraction for major use cases
- forgive me but ... a kinda tough-to-shake sense that the design might have been driven by enterprise interests more than user needs?
I’m here because of something like: “we’d like our users to be able to securely sign in using Windows Hello, Apple Touch ID, etc, like they’re used to doing from native apps, possibly obviating the need for a password”. Part of what’s been confusing about WebAuthn is the emphasis it seems to place on non-discoverable creds, which — maybe I’m misunderstanding something here, but — don’t seem super applicable to typical users of typical apps? Our users don’t own Yubikeys.
I’m glad the API exists (and that much smarter folks than me are working on it). The above is a bit vent-y, so I want to be clear that even though it’s criticism, the work that’s gone into the API is still appreciated.
(Above is collapsed cause it’s tangential and very “general opinion-y”.)
My expectation personally is that we see WebAuthn evolve to indicate broader actions, and to have the client (browser/platform) taking on more responsibility to mediate RP requests
If I’m picturing what you mean correctly, I think that’s my hope as well: more abstraction / higher level API that corresponds more closely to the intended effects from a user experience POV.
I don’t quite understand why “this is problematic for non-discoverable” would also have to mean “so it can’t be done for discoverable creds, either”. Even if there’s a future where a solution is found for updating or support-checking of non-discoverable creds, is there a problem with throwing for those cases in the mean time, unlocking the capabilities for discoverable creds?
Non-discoverable credentials are often immutable, and store information within the credential handle. They also are allowed to not save/return metadata like display names, as their use case is usually done after selection (via a first factor).
Since they are immutable, they wouldn't be so much an update as a replace.
Separate from that is the issue that the credential may in a significant number of cases not be passively addressable when such a store or replace was attempted by a site - even immediately after authentication, as the communication channel may be part of the user presence check (e.g. NFC tap to log in).
That is the primary conflict:
- Credentials in general may not be updatable without the client taking over UX and pushing the user to go through a presence ceremony
- Credentials may not be available, e.g. I don't have the Authenticator on me or have a USB-C to A or USB-A to lightning adapter with me
- In all existing authenticators AFAIK, credentials are not updatable, rather you create a new credential which may or may not invalidate the ability to use the old credential.
- Thus if replacing a credential fails in its transaction between the authenticator and the RP back-end systems, you may have just lost the ability to authenticate
So it could be that the ability to update be limited to a small subset of cases, e.g. credentials on currently connected authenticators, via a credential handle, on authenticators capable of doing a best-effort update vs a credential (without underlying public key or credential handle replacement), confirmed by the user via client UX to prevent abuse scenarios.
If any of this wasn't true, various steps would need to be taken to make the different failure cases not leak information to the RP, which may have negative UX impact - e.g. user prompt to attempt to insert authenticators to see if they support the RP request, user error dismissal so that the RP cannot determine from error messaging or timing if the user rejected the request or if the request was simply responsible to perform, etc.
The RP would not be able to have heuristics to guess if the request would work or not except through attestationsor user-agent guessing on underlying platform authenticators.
What would mostly work (today) would be a user-driven flow e.g. management screen "your displayed name recently changed, would you like to update what is displayed during authentication?" The user would do two user presence checks twice - first to confirm it is the existing credential, then again to register a credential with updated information. This would be treated as a new credential registration in terms of acceptance processing (e.g. attestation checks, etc), with the added bookkeeping step of deleting the old discoverable credential public key and handle.
The act of creating a new discoverable credential with the same underlying user identifier will replace the prior credential per CTAP. On some authenticators, you may see them replace regardless of underlying user identifier (e.g. one discoverable credential per site). Note this still has the 4th concern above - if a transient network failure causes the new credential not to be stored by the RP, you may have disrupted the ability of the user to authenticate.
I’m curious to understand what these scenarios might look like. Since other Credential types permit updating the user/account display fields today without mediation, is there something unique about PublicKeyCredential which changes the equation?
From https://w3c.github.io/webappsec-credential-management/#user-mediated-storage :
Credential information SHOULD NOT be stored or updated without user mediation. For example, the user agent could display a "Save this credential?" dialog box to the user in response to each call to store().
PublicKeyCredentials have an additional difficulty with store, in that the credential you supply to a store() operation cannot be a working credential object - the browser can neither gain access to nor supply a private key. So a store-as-update would only work if an authenticator had the private key, and thus more care needs to be taken not to leak information about what credentials may or may not be available to a client.
(Not directly related, but:) It’s starting to look like I’ll be returning from my journey through WebAuthnLand with nothing to show for it apart from some new knowledge. The showstopper was learning (rather late...) that if you use
get()
to “discover” a discoverable credential, then if there are none*, the agent surfaces a prompt anyway: “Plug in your USB device”. This would bewilder the majority of our users and would seem like a bug — or even something malicious — for those who haven’t yet created an account. I had been under the impression that passwordless auth was already possible with WebAuthn, but afaict it’s still a bit out of reach.
There are certainly improvements possible to the user experience, both in pushing for a consistent UX with the tools we have today, and in improving the tools in the future. A recent issue describing some of the future work being discussed is at #1637.
@dwaite I was a bit confused here at first by the edits — but it looks like what happened is that you’d intended to quote parts of my last comment in a reply rather than edit what I had written?
See also: #1779. Can we close this as superseded?
Agreed, since we did address some of the issues on the original post.
closing to consolidate discussions on this topic. please continue discussions here: https://github.com/w3c/webauthn/issues/1967