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

Why does credentialId need to be unique across all users? #1403

Closed
epheat opened this issue Apr 6, 2020 · 6 comments
Closed

Why does credentialId need to be unique across all users? #1403

epheat opened this issue Apr 6, 2020 · 6 comments
Assignees

Comments

@epheat
Copy link

epheat commented Apr 6, 2020

Section 7.1.17 of the WebAuthn specification states that during a registration ceremony, the Relying Party should ensure that the incoming credentialId is not already assigned to any other user.

  1. Check that the credentialId is not yet registered to any other user. If registration is requested for a credential that is already registered to a different user, the Relying Party SHOULD fail this registration ceremony, or it MAY decide to accept the registration, e.g. while deleting the older registration.

I understand that this is a requirement within the scope of a single user -- if it were allowed, there would be no way to distinguish between the two registered credentials. However, I'm trying to dig deeper into why this is a requirement across all users in the case where the Relying Party decides to key its credentials off the user handle, or even another opaque identifier for which credentialId is just a property.

This issue is discussed in #579, but doesn't go into depth about why the uniqueness restriction is in place. Basically, my question is: when is it appropriate for Relying Parties to break that SHOULD clause in Section 7.1.17? Are there specific threats being mitigated by this uniqueness restriction across all users?

@dwaite
Copy link
Contributor

dwaite commented Apr 7, 2020

Three reasons which quickly spring to mind:

  1. The statistical probability of a credential id repeating should be high enough that it is more likely something went wrong or that this is an attempt at an attack
  2. Predictable credential IDs could be used to track a user across services, say a credential ID which is a combination of a device serial number and a monotonically-increasing counter.
  3. The credential id is returned on getAssertion, and could be used as a global identifier on a particular website.

@Kieun
Copy link
Member

Kieun commented Apr 7, 2020

There are resident key use cases (client side discoverable credential) where the RP tries to authenticate the user without any credential id. Then, the browser or FIDO client tries to list up all the available credentials and prompt to the user to select the account (among multiple accounts). After the user selects the appropriate account and performs user verification, the authenticator will return assertion with credential id. With this credential id, the RP could identify the user and public key for assertion verification.
If the credential id is not unique across all users, the server needs to look up all the matched credentials and perform signature verification until it gets verification success. Also, RP will have no idea whether the key was not registered before or signature verification fails.

@epheat
Copy link
Author

epheat commented Apr 7, 2020

Even in the case of resident keys, won't the authenticator return the selected user handle alongside the assertion? Then, based on that received user handle the RP could look up just the credentials for that user, find the match for credentialId (since it would be unique within the scope of that user), and continue with the assertion verification.

@emlun
Copy link
Member

emlun commented Apr 8, 2020

There's no hard technical requirement for it, it's rather a defense against an opportunity for a rare and subtle bug. Authenticators generate credential IDs independently, so it's possible that two authenticators could generate the same credential ID. This should in theory be astronomically unlikely, but whether due to implementation bugs, bad random number generation, etc., it could conceivably happen in practice. Since credential IDs are generally expected to be universally unique, it's prudent to not register them more than once each. But if you do make sure the correct user owns each credential, I don't think there's any danger in allowing each credential ID once per user.

@epheat
Copy link
Author

epheat commented Apr 8, 2020

Thanks for the responses! Seems it's not a requirement for the specification, but skipping the uniqueness check introduces the possibility of accidentally assigning the same credential to multiple users, potentially allowing them to impersonate each other. RPs should thus tread lightly if they decide to skip the uniqueness check across all users.

One more concern I had is related to authenticators that offload the storage of their private keys by encrypting them and using that as the credentialId. My initial thought was that if two independent authenticators using this technique somehow end up with the same credentialId, they might be able to impersonate eachother. However, I don't think this is true since they would each have their own private encryption key, and would thus interpret that credentialId differently.

@emlun emlun self-assigned this Apr 8, 2020
@emlun
Copy link
Member

emlun commented Apr 9, 2020

Indeed, that shouldn't be a problem. Like you say, the authenticators would have different wrapping keys, so even if they do successfully generate signatures, only one of them would generate a signature that matches the public key registered with the RP. Of course, if the RP has the same credential ID registered with two different public keys, then there would be some room for confusion as discussed earlier.

It seems to me like all questions here have been answered now, so I'll close the issue. You're welcome to re-open it if there are more things you'd like to discuss.

@emlun emlun closed this as completed Apr 9, 2020
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

5 participants