W3C home > Mailing lists > Public > public-webappsec@w3.org > April 2017

Re: Splitting "Credential Management"?

From: Mike West <mkwst@google.com>
Date: Tue, 4 Apr 2017 15:34:23 +0200
Message-ID: <CAKXHy=er1URVn8J6tRpCDHLNMgrsBJDCSZ1zf2U2sqXp_3g-2w@mail.gmail.com>
To: Jeffrey Yasskin <jyasskin@google.com>
Cc: "public-webappsec@w3.org" <public-webappsec@w3.org>, Dominic Battre <battre@google.com>, Václav Brožek <vabr@google.com>, Angelo Liao <huliao@microsoft.com>, Peter Dolanjski <pdolanjski@mozilla.com>, Daniel Bates <dbates@webkit.org>
On Sat, Apr 1, 2017 at 12:59 AM, Jeffrey Yasskin <jyasskin@google.com>
wrote:

> Thoughts on the new merged version at https://w3c.github.io/webap
> psec-credential-management/:
>

Thanks! I appreciate the thoughtful feedback!


> 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.


>   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. For
`PasswordCredential`, this is
https://w3c.github.io/webappsec-credential-management/#store-passwordcredential,
and it stores the ID, name, icon, origin, and password. For
`FederatedCredential`, it's
https://w3c.github.io/webappsec-credential-management/#store-federatedcredential,
and stores the ID, name, icon, origin, provider, and protocol.

For these types of credentials, `store()` is meant to update the contents
of the credential store with whatever the website tells us is working. We
expect `store()` to be used for password change forms, for instance.

For WebAuthn, the model is probably different. Currently, the PR at
https://github.com/w3c/webauthn/pull/384 defines the internal method as a
noop, but there are two scenarios to think through:

1. The website is registering a webauthn authenticator via
`ScopedCredential.create()`. In this case, we have all the information from
the RP, and we have the whole response from the device. It's arguable that
the user's interaction with the device would be enough to justify storing
the relationship for future use in a chooser.

2. The website is asking for a `ScopedCredential`, but the UA has no idea
whether one exists. So we ask the user, they insert their security key, and
it responds in a reasonable way to a challenge. In this case, it's probably
also reasonable to treat the user's interaction with the device as
justification to store the relationship, but we don't have the information
we would have in the registration step. In this case, `store()` might still
be useful.

2) Nit: It's odd to have both NoInterfaceObject and Exposed=Window on
> CredentialUserData.
>

Yup. Good eye!
https://github.com/w3c/webappsec-credential-management/commit/5a18aa36d44c31c67bd4b9613e56e4bc16a598af


> 3) Nit: https://w3c.github.io/webappsec-credential-management/#construct-
> federatedcredential-data has a title of "The PasswordCredental ...".
>

Oh, copy/paste... I changed the ID, at least!
https://github.com/w3c/webappsec-credential-management/commit/12799420021198c3660d450c5b723e37245da0ed

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.


> 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.


> When get() is called with options that match zero or >=2 active
> credentials, the UA may need to show a chooser. It should prioritize active
> credentials over known credentials over unknown credentials, but it needs
> to let the user select an unknown credential. In some cases, the get()
> options might narrow down the set of credentials so that the UA can call a
> single OS API to do the operation (e.g. "publicKey" with no active
> credentials). In that case, the UA should still tell the OS to insist on
> some sort of mediation.
>

I think this makes sense, but I think we might also need a chooser in cases
where there's exactly 1 "active" credential of a given type. See the
multi-login example above.


> 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"?

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?

-mike
Received on Tuesday, 4 April 2017 13:35:19 UTC

This archive was generated by hypermail 2.3.1 : Monday, 23 October 2017 14:54:22 UTC