Re: Splitting "Credential Management"?

On Tue, Apr 4, 2017 at 5:23 PM, Jeffrey Yasskin <jyasskin@google.com> wrote:
>
> 1) I'd like to start coming up with terms to distinguish "concept 1", the
>>> thing you possess that gives you the right to do something, say, log in as
>>> User X; and "concept 2", the proof that you have that thing. We're going to
>>> need this for full federated credentials, SMS auth, and WebAuthn. Some
>>> options: "credential"/"credential proof", "credential"/"attestation",
>>> "credential generator"/"credential", "identity"/"credential". I lean toward
>>> the first pair and will use those here, but I'm happy to take anything that
>>> avoids conflating them.
>>>
>>
>> I agree with you that "concept 1" and "concept 2" are different, but it's
>> not clear to me that a developer would care. That is, if I'm understanding
>> the distinction you're drawing, websites are always looking for a "concept
>> 2", and it just happens to be identical to the "concept 1" in the case of
>> passwords.
>>
>
> I can buy that, in which case using "Credential" for the only concept the
> page needs would be really nice. I'd still like to have the spec *talk*
> about the distinction between the concepts so that devs and implementers
> reading it easily understand that passing around your webauthn credential
> isn't intended to hand out the private key.
>

Which spec?

The current draft of the Credential Management spec says "From a
developer’s perspective, a _credential_ is an object which allows a
developer to make an authentication decision for a particular action." (
https://w3c.github.io/webappsec-credential-management/#core). What would
you like it to say instead? Should we call that a "credential proof"
instead? If so, should we call the `Credential` object `CredentialProof`? I
guess I'm ok with that if y'all think there's value in the distinction.

  a) Does store() merely record that a particular CredentialProof worked
>>> for a site, or does it save a whole Credential? The first is consistent
>>> with the current behavior for "federated", and would imply that a WebAuthn
>>> CredentialProof could be stored too. If the second, we'd change store()'s
>>> parameter to be Credential, and passwords might be the only valid argument.
>>>
>>
>> `store()` delegates to an internal method on the interface, so it can do
>> whatever makes sense for a particular credential type.
>>
>
> While that's true
>

Technically correct is best correct. :)


> it'd be nice if we had a consistent story for the meaning instead of a
> bunch of one-off behaviors. I'm getting more comfortable with "this proof
> worked for this site", and then we can figure out how to implement that for
> each credential type.
>

I think that's a reasonable summary, yes.


> 4) I think we'll need the UA to store a notion of:
>>>   a) Which credentials successfully log into which identities for a
>>> given site. Call these "known" credentials. An "identity" is just the
>>> content of CredentialUserData.
>>>   b) Which credentials have been used successfully since the most recent
>>> requireUserMediation(). Call these the "active" credentials?
>>>
>>>   When get() is called with options that match exactly one "active"
>>> credential, the UA should try to get a proof for that credential, whether
>>> it's a password, a federated identity, or a WebAuthn authenticator. Some of
>>> these will do their own mediation, but the UA shouldn't show an extra
>>> chooser.
>>>
>>
>> How would a user change accounts in this world? Like, consider Google's
>> (absurd) multi-login? If `accounts.google.com` wanted to allow you to
>> sign in as `user2` when you're already signed in as `user1`, we support
>> that today by forcing a chooser in cases where we don't have a single,
>> unambigious credential of the type you're asking for.
>>
>
> A user would *change* accounts by having the site call
> requireUserMediation().
>

How would the site know to do that? I suppose there would always be a
"Change account" button or something similar?


> *Maybe* an extra argument to get() that forces mediation but doesn't
> otherwise clear the active set? ....
>

I was thinking about this as well this morning. It would probably make
sense (and make things less opaquely-named) to replace the `unmediated`
flag with something like:

```
enum MediationRequirement {
  "without-user-mediation",
  "whatever",
  "with-user-mediation"
};

dictionary CredentialRequestOptions {
  MediationRequirement mediation = "whatever";
}
```

Maybe with a better name for that middle one...

This is where a .cancel() operation
>>> <https://github.com/w3c/webauthn/issues/380> would be useful.
>>>
>>
>> This seems like it would be generally useful, yes. I wish that TC39
>> hadn't punted on the problem of cancellable promises, as it's what we need
>> here.
>>
>> Fetch has a potentially-more-complicated-than-we-need controller model,
>> which we could certainly copy. That is:
>>
>> ```
>> var controller = new CredentialRequestController();
>> navigator.credentials.get({ ..., signal: observer.signal }).then(...);
>> controller.abort();
>> ```
>>
>> There's probably some value in just following along with the path they're
>> cutting, even if it allows more flexibility than we require. It also has
>> the advantage of not changing anyone's existing code if they don't actually
>> care about cancellation.
>>
>
> +1. Maybe we can get a generic CancelController object so that each spec
> doesn't have to create its own.
>

I was just talking with Jake (CC'd) about this this morning; I think we
agree that it makes sense to put together a more general controller
interface from which FetchController can derive (and which we could use
directly).

SMS and email auth might be interesting cases here: users might want one of
>>> them to be the active credential, but still want to confirm receiving an
>>> SMS or email. I guess we could treat that as the credential type doing its
>>> own mediation?
>>>
>>
>> If the browser does the work without asking the user, how would either be
>> considered "mediated"?
>>
>
> I was suggesting that SMS might always need to be mediated, even if it's
> the only active credential.
>

Got it. I agree!

5) The credential store's different pieces might have different lifetimes:
>>>   a) Passwords and UA-stored private keys need to survive "clear
>>> browsing data", and so they need more user approval to be stored.
>>>   b) Knowledge that the user has a removable WebAuthn authenticator or
>>> has used SMS auth with a particular site can be cleared with a site's
>>> cookies, and so maybe doesn't need any user approval to be stored.
>>>
>>
>> What's the relevant distinction between things in a) and b) that would
>> lead you to treat them differently?
>>
>
> If you delete (a), the user's ability to log into the site completely goes
> away. If you delete (b), the user might have to do more navigation to get
> back to the site, but they can still log in.
>

Ok. So you'd treat the latter as similar to cookies, as they don't in
themselves constitute the entirety of the credential, and can be easily
regenerated. I see.

-mike

Received on Wednesday, 5 April 2017 09:43:54 UTC