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

Add notion of forbidding resident credential creation #1149

Closed
equalsJeffH opened this issue Jan 29, 2019 · 26 comments
Closed

Add notion of forbidding resident credential creation #1149

equalsJeffH opened this issue Jan 29, 2019 · 26 comments

Comments

@equalsJeffH
Copy link
Contributor

equalsJeffH commented Jan 29, 2019

Update 16-May-2019:
This issue was improved by merging PR #1191, and may be addressed (in practice) by the latter. Need to assess this.


**Original post 28-Jan-2019**: Today, when making a credential, an RP can specify that they either require a [(client-side) resident credential](http://w3c.github.io/webauthn/#resident-credential), or that they can live with either that or the alternative server-side resident credential (think U2F).

Thinking forward to how we’d like to migrate users with security keys to the “resident credential” world (and thus enabling password-less and typing-free flows), we propose that we add an additional value to the requireResidentKey parameter during Create. With this, we’ll end up with ResidentCredential being one of three values: {Required, Preferred, Forbidden}:

Required maps to the current setting of requireResidentKey = true, explicitly requiring the authnr to create a resident credential.

Preferred, indicates that the RP prefers to create a resident credential, but would also be fine with a non-resident credential (aka "server-side cred"), if that’s the only thing the authenticator supports. Presently, requireResidentKey = false largely maps to this.

Forbidden will map to a new, explicit sense of “false”—it’s better defined—it means that the authenticator must explicitly create a server-side resident credential.

See also: Credential Storage Modality and Authenticator Taxonomy

@equalsJeffH
Copy link
Contributor Author

equalsJeffH commented Jan 30, 2019

NOTE: some have been thinking that this would be a change to WebAuthn only (i.e., no CTAP changes) since this change only affects how the browser selects eligible authenticators for that specific transaction.

Actually, it is seeming to me that the above claim is not correct -- i.e., that CTAP is indeed also affected and will require changes:

Presently, CTAP only specifies specific behavior for rk=true. If rk is false, whether or not we are creating a client-side resident credential, or a server-side resident cred (aka "server credential"), appears to be implicitly left up to the authenticator.

E.g., present CTAP language is in Step 10 of CTAP's authenticatorMakeCredential() operation

See also the webauthn language wrt "requiring a resident key": ..and also the "credential storage modality" section whose last paragraph says:

Note that a resident credential capable authenticator MAY support both storage strategies. In this case, the authenticator MAY at its discretion use different storage strategies for different credentials, though subject to the requireResidentKey option of create().

..note also that the above-menioned werbauthn language for requireResidentKey says only this:

"If the parameter is set to true, the authenticator MUST create a client-side-resident public key credential source when creating a public key credential."

..thus leaving the requireResidentKey=false behavior up to the client platform and/or the authenticator (and given present CTAP spec language, it apparently is implicitly left up to the authnr).

cc: @christiaanbrand

@dwaite
Copy link
Contributor

dwaite commented Jan 31, 2019

For clarification, why would a relying party require this Forbidden behavior?

@emlun
Copy link
Member

emlun commented Jan 31, 2019

@dwaite That's a good point. Under the assumption that authenticators never share any of their secrets with the outside world - e.g., by allowing to sync a wrapping key with another device - there should be nothing a server-side-resident key can do that a client-side-resident key cannot, so there shouldn't be much reason for an RP to ever prefer a server-side-resident key. And if we remove that assumption, then the authenticator could sync the credential private key just as well as a wrapping key, so the same conclusion should hold in that case.

On the other hand, there is good reason for an authenticator to prefer server-side-resident keys if it has limited key storage capacity. But adding the option for the RP to forbid client-side-resident keys does not in any way restrict the authenticator's option to create a server-side-resident key.

@Kieun
Copy link
Member

Kieun commented Jan 31, 2019

I'm not sure that there is a case where the RP requires forbidden behavior explicitly. But the thing is that RP should have information whether the key is located in the client or not. With that information, RP may provides authentication user flow.

@emlun
Copy link
Member

emlun commented Jan 31, 2019

@Kieun Yes, but that is a separate issue: #1060

@ve7jtb
Copy link
Contributor

ve7jtb commented Feb 6, 2019

If resident forbiddin is the third option then setting that would not work with some platform authenticators that always make resident credientials.
That will cause RP to always ask for preferd to be the most compatable.
If all RP allways ask for preferd external authenticators will fill up with resident connections afer the first x sites. Then only be able to make non resident credentials untill the user uses a credential management UI to delete a credential.

I would rather have a default that lets the authenticator decide and report the credential type to the RP.
That lets RP who don't care about using browser side credental selection, get something that can work passwordless in a identifier first flow but not create needlessly bad user experiences as a side efect.

@equalsJeffH
Copy link
Contributor Author

See also fido-alliance/fido-2-specs#617 and fido-alliance/fido-2-specs#624

@equalsJeffH
Copy link
Contributor Author

@ve7jtb notes on todays webauthn call that perhaps what we need is four states here:

  • must be resident
  • resident preferred
  • I don't care
  • forbidden

@emlun
Copy link
Member

emlun commented Feb 13, 2019

...of which "forbidden" seems unlikely to ever be used, because it adds a restriction relative to "I don't care" while providing no added benefit. :)

@dwaite
Copy link
Contributor

dwaite commented Mar 13, 2019

Since an authenticator could decide to give a resident credential in place of a non-resident credential, this is almost a misnomer in the spec itself. What the relying party really cares about is whether an assertion can be made within the UX the party wants.

Thinking of this as a list of behaviors, to register a credential which either:

  1. works without a handle presented in an allow list, as a primary factor
  2. requires a handle in the allow list, as a secondary factor
  3. prefers a credential which works without a handle, which will work as a primary factor. A secondary factor credential can be registered as well.

This does mean that in case 2, the credential must not be presented as an option if a request is made without the corresponding handle being presented in an allow list. And in case 3, the relying party must know whether a handle is required or not for creating assertions in the future.

I suspect there isn't a usability case for forbidding authenticators from creating resident credentials, because a resident credential is a superset usage-wise compared to a non-resident one.

@equalsJeffH
Copy link
Contributor Author

This is part of addressing issue #991

@akshayku
Copy link
Contributor

akshayku commented May 8, 2019

Please specify the use case why its needed?

cc: @christiaanbrand

@nadalin
Copy link
Contributor

nadalin commented Jun 12, 2019

@christiaanbrand Can we close this ?

@christiaanbrand
Copy link

Forbidden is a requirement here. Else, how am I suppose to make a credential on a security key, if I never want the silly key to prompt my user for PIN. We arrived at a point where the folks from MS told me that they'd be okay to not prompt for PIN (even if the "security key does have a PIN set up"), but only if it's not a resident credential. How am I suppose to enforce NOT CREATING a resident credential if I don't have this option?

@sbweeden
Copy link
Contributor

sbweeden commented Jun 12, 2019

Why can't this be achieved with userVerification="discouraged", residentKey="discouraged" ?

I don't think you can force an authenticator to not store a resident credential if it so chooses.

@christiaanbrand
Copy link

it seems like we're debating the meaning of words in the english language. I want to rename "discouraged" to forbidden. I don't want the key to EVER make it if I say "no".

@sbweeden
Copy link
Contributor

I believe we need to hear from @akshayku on this - I thought I heard him say that Windows Hello will always create a resident credential.

@akshayku
Copy link
Contributor

akshayku commented Jun 12, 2019

@christiaanbrand: Practically, You have the semantics that you want from discouraged. I am assuming that you don't want to prompt for PIN for external authenticators. I am also assuming that you are OK with Windows Hello?

By and large, we agreed on that for non-resident keys on external authenticators. But that is not an absolute guarantee from CTAP spec. That still depends on how authenticator wants to differentiate themselves. CTAP spec allows them to do more than asked for.

Practically speaking, when you set it to discouraged, a single link will work for Platform authenticator (like windows hello where we will always ask for user verification) and external authenticators (where for non-resident keys, you will not have a PIN).

Discouraged value really works for almost all the cases.

Instead of renaming, we can add another value of forbidden if that's what you want. Setting it to forbidden will not work for 'Windows Hello' and also for some external authenticators who will distinguish themselves and will always ask for user verification. And CTAP spec allows them to do more than asked for. Platform will have to NOT allow such users/Authenticators for the request. I am not sure whether you want to NOT allow such authenticators.

Did I clear the confusion?

@sbweeden
Copy link
Contributor

I can't see how the platform authenticator for Android would work in that case either. Any RP wanting users to register on any available authenticator (platform or portable) would therefore never use forbidden, even if such a thing was offered. It would destroy the UX and limit registration capabilities.

@dwaite
Copy link
Contributor

dwaite commented Jun 13, 2019

If the goal is RP UX that prevents asking for a PIN, the change should be in WebAuthn - to forbid creating credentials that will require a PIN (or perhaps any form of UV) at authentication time.

Correct me if I'm wrong - CTAP is important, but it does not preclude other roaming authenticator specifications in the future, and also does not dictate platform authenticator behavior. It also isn't the spec that a RP should be looking at for WebAuthn API behavior.

@Kieun
Copy link
Member

Kieun commented Jun 13, 2019

Is forbidden about credential source or user verification? The original post is introducing forbidden instead of discouraged for credential source and the later discussion looks about UV.
For require resident key option, why do we need forbidden?
Is there any reasons for RP to only allow non-residential credential? Many of here understand that we don't need forbidden for rk.

For UV, I know the intention for adding this where the RP doesn't need UV for the authentication.
It's better to get motions from the authenticator vendors since this may affect their business.

@ve7jtb
Copy link
Contributor

ve7jtb commented Jun 13, 2019

I think talking about how the key is stored is not really the heart of the issue.

I think the proper thing to consider is if the credential requires an allow list.

Now with the credprotect extension, the RP can create a credential that must be used in get with a allow list or a pin is required if the credential is used without an allow list. That is independent of how the credential is stored.

The issue Christian has is being able to suppress the prompting for a UV factor separate from UP.
I think everyone is OK with the make credential behavior of U2F, and removing the current requirement to always do UV even if UV discouraged is sent during make credential if UV (or PIN) is set on the device.

Perhaps we should look at the reasons people have for requiring UV for credentials that can be used without an allow list, before we mess too much with trying to prohibit resident keys and perhaps unintended consequences from adding more flags.

One way to do it might be that if the RP sends UV discouraged in the make credential request, the browser would know that it needs make a CTAP request for a non resident credential without prompting for PIN.

Or with an authenticator that supports credprotect would setting userVerificationOptionalWithCredentialIDList also be OK to create without requiring a PIN for Make Credential.

I think the desired behavior is probably more along the lines of make a credential with UV = Discouraged and let the WebAuthn client decide how best to do that if it is a non resident credential or a resident credential that can only be used with an allow list based on the authenticators available.

Our problem is more that UV = discouraged is overridden.

RP that send UV = discouraged just need to be willing to accept credentials that may be non resident.
If we report back if the credential can be used without an allow list, or not I don't see much of a problem.

If the RP asks for resident = true and UV = discouraged then that would just be an invalid combination.

Perhaps it is UV that we need an extra state for, Forbidden, Discouraged, Preferred, Required? That might be a better way to get at what I think Christian is looking for. Or just change the interpretation of discouraged for make credential.

@christiaanbrand
Copy link

I must say, this is all incredibly confusing to me.

Let me start from the beginning again:

I want the U2F use-case in FIDO2. Ie. I want, as an RP, to be able to make a credential, that does not require a PIN during BOTH the creation and signature generation. Even when the "security key has a PIN" I don't want one to be asked. As long as I have a way to do that, I'm good.

I thought that we said that we're all okay with a credential being created without asking for UV, AS LONG AS THE CREDENTIAL always has to be exercised using an AllowList (ie. it's not resident, because otherwise a bad website can fill up my key). I don't agree with this argument, but that's the one that was made.

So, in my mind, if I can only get this behavior if I set UV=discouraged AND force a non-resident credential creation on the key, I need way to do that. If now, we don't care anymore about the resident vs non-resident requirement, that's fine, but that needs to be written down in the spec.

All I want is a way to make a credential on a security key, that NEVER EVER EVER asks for a PIN during creation. In the current setup, what will I send via WebAuthn to accomplish that?

@sbweeden
Copy link
Contributor

So my take on @christiaanbrand 's requirement is that this is how things should behave today (even in L1) if navigator.credentials.create is called with requireResidentKey=false (or absent, since that's the default), and userVerification=discouraged. The simple fact though is that this isn't how all browser+authenticator combinations behave - the behaviour is inconsistent across browsers (CTAP1 vs CTAP2) and when using platform vs roaming authenticators, and even changes depending on some roaming authenticator's enabled capabilities (if a PIN is set vs not set). I don't think a functional spec change is really required or desirable but I do think it's worth getting the editors to weigh in on whether or not they concur that the combination of modifiers I have suggested should result in the requested behaviour. If so, then the spec could provide specific direction regarding same.

@agl
Copy link
Contributor

agl commented Jul 17, 2019

From the call of 2019-07-17, we are leaning towards closing with issue with no action.

Firstly, “resident” here means discoverable, i.e. can be found with an empty allow-list. It has always been the case that authenticators may choose to implement credentials in a stateful manner if they wish.

With the current CTAP2 specification, an authenticator can make credentials discoverable at will. I hope to change that in the future, but that's the reality at the moment and thus the reality for all existing CTAP2 authenticators.

Given that, if rk=forbidden was defined then, in order to meet that prohibition, a platform would have to refuse to create credentials on any current CTAP2 authenticator. (Because they could be making discoverable credentials behind the scene and there's no way for the platform to know.) That seems like a terrible experience and thus we expect that no RP would ever actually set that option. Therefore why have it?

@christiaanbrand says above that his desire is to avoid PIN prompts as an RP. Today there's a problem with that because, once a PIN is set on a CTAP2.0 authenticator, a PIN is needed to create any sort of credential. That's being addressed for CTAP2.1 and, if the authenticator supports U2F, Chromium will work around it today by using the U2F interface to create the credential. But all that is independent of whether a credential is discoverable so having the concept of “forbidden” resident keys doesn't seem to help avoid PIN prompts any more than “discouraged” does.

see also: https://github.com/fido-alliance/fido-2-specs/pull/661

@equalsJeffH
Copy link
Contributor Author

given the above, we're closing this. it can be re-opened if someone disagrees strenously

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

10 participants