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

Plumb User ID through #558

Merged
merged 10 commits into from
Oct 4, 2017
Merged

Plumb User ID through #558

merged 10 commits into from
Oct 4, 2017

Conversation

christiaanbrand
Copy link

@christiaanbrand christiaanbrand commented Sep 8, 2017

We need to plumb the custom user id that the RP gave the authenticator during MakeCredential back through to the RP when doing getAssertion.
Closes #556


Preview | Diff

christiaanbrand added 6 commits September 8, 2017 15:56
We need to plumb the custom user id that the RP gave the authenticator during MakeCredential back through to the RP when doing getAssertion.
@nadalin nadalin added this to the WD-07 milestone Sep 12, 2017
@nadalin
Copy link
Contributor

nadalin commented Sep 13, 2017

So the Privacy considerations section should be a statement about the issue of sharing PII with someone you were not expecting

@jyasskin
Copy link
Member

jyasskin commented Sep 13, 2017

In response to the discussion today, I suggest adding a sentence to the Security/Privacy Considerations section along the lines of:

The authenticator can be used to retrieve a user ID given a credential ID, so if the user ID is PII, the credential ID is also PII.

This might be wrong: it assumes that if I need to combine two things to get some PII, then each of those pieces are also PII individually.

Edit: The above was wrong: exporting the user ID with the assertionresponse allows someone with physical access to the authenticator to turn an RP ID into a user ID. That's the risk that needs to be highlighted in the privacy considerations section.

@wseltzer
Copy link
Member

wseltzer commented Sep 13, 2017 via email

@jyasskin
Copy link
Member

@wseltzer @nadalin, I suspect we shouldn't try to make this spec a tutorial on how to protect PII. We need to identify anything that might be PII by surprise, but then trust RPs to know what they need to know about protecting it.

@leshi
Copy link
Contributor

leshi commented Sep 14, 2017

Edit: The above was wrong: exporting the user ID with the assertionresponse allows someone with physical access to the authenticator to turn an RP ID into a user ID. That's the risk that needs to be highlighted in the privacy considerations section.

We only want the user id for the single factor use case (i.e., resident keys). In such a use case, the attacker has to convince the authenticator that it's the legit user -- so know the right PIN or get the device to cough up the assertion. Once the assertion is coughed up -- even if there is no user id -- the attacker can just give it to the RP and not only know the user id but actually see the user data... So IMHO, this is not too much of a concern. WDYT?

@emlun
Copy link
Member

emlun commented Sep 15, 2017

Why is the user ID necessary for getAssertion? Even for the single factor use case, isn't it possible for the RP to identify the user from only the credential ID even with no allowCredentials? For example:

  1. Setup: The RP has an internal table linking credential IDs to public keys and internal user IDs, and the user has previously registered a credential with the RP
  2. The user initiates an authentication ritual (providing no additional info at this point)
  3. The RP generates a challenge and sends a PublicKeyCredentialRequest (with no allowCredentials) to the client
  4. The authenticator chooses a credential and generate an assertion
  5. The RP receives the PublicKeyCredential with an AuthenticatorAssertionResponse containing a credential ID and a signature by that credential
  6. The RP looks up the public key from its table using the credential ID and verifies the challenge signature
  7. If (6) fails, the RP asks the user to try again with a different credential
  8. If (6) succeeds, the RP looks up the user ID from its table using the credential ID and initiates an authenticated session for that user

Shouldn't that work?

@christiaanbrand
Copy link
Author

It's a bad idea to have some external system with limited context responsible for generating unique indices for a database. We really need to key off something we control, not the authenticator.

@emlun
Copy link
Member

emlun commented Sep 19, 2017

That does sound like a very valid point.

@jyasskin
Copy link
Member

@leshi

We only want the user id for the single factor use case (i.e., resident keys). In such a use case, the attacker has to convince the authenticator that it's the legit user -- so know the right PIN or get the device to cough up the assertion. Once the assertion is coughed up -- even if there is no user id -- the attacker can just give it to the RP and not only know the user id but actually see the user data... So IMHO, this is not too much of a concern. WDYT?

I agree in the single-factor use case. I don't see anything in the patch that limits the privacy leak to the single-factor case. Am I missing something, or should we explicitly say that the authenticator shouldn't release the user ID when, e.g., it's been passed a credential ID?

@christiaanbrand
Copy link
Author

Sure. But only the actual RP will get it back, and if you have the credential ID (and can masquerade as the RP) you already have the corresponding account, right? Do we really need to limit this?

@jyasskin
Copy link
Member

@christiaanbrand Anyone with physical access to the authenticator can pretend to be any RP, and if they can also convince the authenticator that they're the user (trivial for second-factor authenticators), they can get the user ID for that RP out.

I'm not certain that's a leak we should worry about, but we should decide whether to worry about it, and we should probably mention it in the privacy considerations section anyway.

Copy link
Member

@jyasskin jyasskin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concerns are postponed to #578. This PR is fine with me.

@jovasco
Copy link
Contributor

jovasco commented Sep 21, 2017

Credential IDs are not guaranteed unique in any way. Unless I missed something in the specs, it is perfectly valid to store all data locally and return a single byte key index.

This has a lot of consequences that are not currently handled, especially in the RP assertion validation algorithm:

  • a Credential ID is not guaranteed unique for a single user on a single RP. (Will happen if you buy two such authenticators and you register them as a pair on every account).
  • You cannot refuse duplicate Credential IDs as this is both valid and, if such an authenticator becomes popular, likely to be relatively common (as all credential IDs will be in the same limited range). Refusing would put the user in a situation he cannot resolve, retrying the registration will just replace the current key entry (as specified) with likely the same index.
  • You need to verify against the public key of every matching Credential ID for this user. If one matches, this is a valid assertion.

It also makes returning the User ID a necessity as you would have potentially thousands (millions) of accounts with this Credential ID for first factor scenarios.

In any case, the specs assume Credential ID collisions are at least unlikely. It might be easier to add a few requirements to promote that than try to handle all the issues.

I've raised an issue for this in the FIDO group. Should I raise one here too?

@leshi
Copy link
Contributor

leshi commented Sep 21, 2017

Thanks, Johan!

I believe that on the last W3C call (https://www.w3.org/2017/09/20-webauthn-minutes.html), we have agreement to plumb userid through -- which will hopefully solve all the aforementioned problems.

Jeff is taking it on himself to review the PR meanwhile.

@akshayku
Copy link
Contributor

@emlun: No, this will not make existing U2F devices incompatible.

You are correct that existing U2F devices cannot store user ID so for U2F devices, authenticatorGetAssertion response will have this field set to null/zero bytes.

This is similar to scenario where AAGUID is not being present in authenticatorMakeCredential response for U2F devices.

User ID is an hint for the RP's for lookup in their databases. User ID is not included in the signature itself. Its an extra information.

@nadalin
Copy link
Contributor

nadalin commented Sep 22, 2017

@akshayku so it looks like this is ready to merge so that we can also merge https://github.com/fido-alliance/fido-2-specs/pull/300

@emlun
Copy link
Member

emlun commented Sep 22, 2017

@akshayku Ah yes, if it's optional then that's fine; I got the impression it would be a required output. But then again, if it's optional then RPs cannot in general rely on it being available. In that case I feel like it might be better to push this into an extension, and reserve the core for the parts that must always be present.

@akshayku
Copy link
Contributor

akshayku commented Sep 22, 2017

This will be required for FIDO 2 devices. For U2F, we have a compatibility story as we anyway have to convert U2F assertion response to FIDO 2 response.

And this is not part of the signature so can't be part of the extension.

@emlun
Copy link
Member

emlun commented Sep 22, 2017

Not in the authenticator data as an authenticator extension, indeed, but couldn't it be returned as a client extension?

Either way there's still the fact that it won't be available from all authenticators, regardless of whether or not it's required for FIDO 2 devices. RPs will still need to handle it not being available, so making it "required" seems rather moot.

@christiaanbrand
Copy link
Author

Why can this not be required for all resident-credential FIDO2 authenticators?

Remember this whole deal is only about resident-credentials. If it's a U2F-type authenticator (even in FIDO2 land) none of this stuff is required. As Jeffrey mentioned yesterday, it should explicitly not be present if the keypair is being used as a second factor.

@christiaanbrand
Copy link
Author

christiaanbrand commented Sep 22, 2017

Just for completeness. I approve this merge, with the understanding that Jeffrey @jyasskin will write up some language which says authenticators should never return userid (or any account info for that matter) when a signature was requested using a CredentialID [this means it's being used as a second factor]. See issue #720

@nadalin
Copy link
Contributor

nadalin commented Sep 22, 2017

@christiaanbrand or @jyasskin please merge

@emlun
Copy link
Member

emlun commented Sep 23, 2017

@christiaanbrand

Remember this whole deal is only about resident-credentials. [...] it should explicitly not be present if the keypair is being used as a second factor.
[...] authenticators should never return userid (or any account info for that matter) when a signature was requested using a CredentialID [this means it's being used as a second factor].

Ah, those pieces of context had gone right over my head. In that case it makes sense. Sorry for making a fuss.

index.bs Outdated
@@ -1721,6 +1725,7 @@ On successful completion, the authenticator returns to the user agent:
- The identifier of the credential (credential ID) used to generate the [=assertion signature=].
- The [=authenticator data=] used to generate the [=assertion signature=].
- The [=assertion signature=].
- The user id associated with the credential used to generate the [=assertion signature=].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whatever name is chosen, use it here too.

@equalsJeffH equalsJeffH self-requested a review September 28, 2017 04:42
@christiaanbrand
Copy link
Author

TODO: Change names to not contain the word userid. It's confusing.

@christiaanbrand
Copy link
Author

How to folks feel about the term "user handle". I've already updated the PR.

@akshayku
Copy link
Contributor

akshayku commented Oct 2, 2017

Looks fine to me.

Copy link
Member

@emlun emlun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree "user handle" seems like a good term. I suggest also updating §4.4 from

Its value’s id member is required, and contains an identifier for the account, specified by the Relying Party.

to

Its value’s id member is required, and contains the user handle for the account, specified by the Relying Party.

Perhaps also add it to the glossary?

@ve7jtb
Copy link
Contributor

ve7jtb commented Oct 3, 2017

Fine with me.

@christiaanbrand christiaanbrand merged commit 23b91fb into w3c:master Oct 4, 2017
WebAuthnBot pushed a commit that referenced this pull request Oct 4, 2017
emlun added a commit that referenced this pull request Dec 20, 2017
As stated in
#558 (comment) and
#558 (comment) the user
handle should not be returned when operating in 2nd factor mode (i.e.,
when given a non-empty `allowCredentials` list).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants