Re: PR #384 CredMan Integration

+1

On 4/11/17, 4:06 PM, "Vijay Bharadwaj" <vijaybh@microsoft.com<mailto:vijaybh@microsoft.com>> wrote:

My 2c on this: I whole-heartedly agree with the approach you advocate at the end of your email, of pulling out the pieces that we all agree on and merging those in first. I would rather debate a small and contained set of known unknowns than large philosophical issues.

My response to Alexei’s proposal was also in this vein: let us lock in our gains where we can, so we can better quantify the risks and open questions remaining. We may realize in the future that our present consensus was a horrible mistake, but even in that unlikely event we are more likely to reach a well-understood conclusion to the debate sooner. If we can capture these consensus items in a PR now, we may have time for a more focused iteration of debate in tomorrow’s call and during the following week.

From: Mike West [mailto:mkwst@google.com]
Sent: Tuesday, April 11, 2017 3:37 PM
To: Alexei Czeskis <aczeskis@google.com>
Cc: Anthony Nadalin <tonynad@microsoft.com>; Hodges, Jeff <jeff.hodges@paypal.com>; public-webauthn@w3.org
Subject: Re: PR #384 CredMan Integration

Hey Alexei! Thanks for your feedback, I'm glad we're continuing the conversation. Apologies for the ridiculous length, but it's midnight, my brain is shutting down, and I'm giving up on making this shorter or more coherent. :P

On Tue, Apr 11, 2017 at 6:05 PM, Alexei Czeskis <aczeskis@google.com<mailto:aczeskis@google.com>> wrote:
I'm all for getting the spec done fast, for getting implementations out fast, and for making the world a better place faster.  If we want to speed things up, I'm not convinced that the PR as it is right now is the right move.  I'm not simply arguing for making fast progress and accepting a messy API landscape in return.  I'm arguing for not venturing into the unknown to find the perfect -- in effect passing on the known-good.

I appreciate the time and consideration y'all are giving the proposal I put forward in #384. I agree wholeheartedly with the admonition against putting the perfect ahead of the good, and while I hope you'll accept a little more discussion (and, unfortunately, probably a few long emails), I don't want to hold you up unreasonably.

That said, I'd suggest that "the unknown" isn't as scary and dark as it might look. Chrome is shipping the credential management API, developers are using it today, and building up expectations about its use that I think we would be well-served to consider and align with. You're entirely correct to suggest that there are interesting questions to consider, but, in my opinion, they're managable in a timeframe that I hope y'all can support.

I believe that in its current form, the merge will cause questions that will take a while to iron out.  I would suggest an alternate approach: hold off on the merge until the proposal does not have as many unknowns.  Maybe that means waiting until version 2.

I agree that merging #384 right now would be a bad idea, given the sincere objections you and Dirk have raised. We should continue conversations like this one to make sure we're on the same page regarding the concepts we're trying to align.

In my opinion, the big reason to be hesitant about this merge is that it takes us down the path of one single .makeAuthFactor() and one single .getAuthFactor() methods.

I suspect you won't be shocked to learn that I think this is a big reason to be excited about the proposal. :)

While I agree that it would be strange to request both a password and a yubico-style security key assertion in a single call to `get()`, the single entry-point approach seems like an essential component of the story for more complicated authenticators that folks might trust as an authentication vector in and of themselves. I tried to sketch this out in more detail at the end of my response to Dirk's email earlier this week: https://lists.w3.org/Archives/Public/public-webauthn/2017Apr/0147.html<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.w3.org%2FArchives%2FPublic%2Fpublic-webauthn%2F2017Apr%2F0147.html&data=02%7C01%7Cvijaybh%40microsoft.com%7Ce8c9319e12f24c03caf308d4812b7cae%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636275471156232104&sdata=Nq4e31ax22lPKqAnI7Nanj4Ei52YkjDDsC1wj4kvfKA%3D&reserved=0>

For example, for usernames and password -- the browser manages identities and shows the UX for selection.  For authenticators such as phones, the phone does.  I'm not sure what the right way to show UX is there.  Maybe it's not a problem for Edge that might just call Hello, but I'm not sure what cross-operating-system browsers such as FF and Chrome would do.

Long term, I think this is a problem we very much need to solve: it should be possible for a developer to transition from passwords to something stronger without throwing multiple, disconnected dialogs up in the user's face.

Shorter-term, I think we have two options:

1.  We enforce a disconnect between the credential types that the user
    agent knows about a priori, and those that require an external
    service for discovery (this might boil down to rejecting calls like
    `get({ password: true, scoped: { ... })`).

2.  We launch something strange to support these kinds of requests, and
    iterate on it. The credential management spec currently suggests
    something like displaying the known credentials in a
    user-agent-controlled chooser, along with a friendly name for the
    type of credentials that could be discovered. That is, given the
    above call to `get()`, the chooser might render:

    *  User/Password 1
    *  User/Password 2
    *  Use a Security Key

    And clicking the last item would nicely push you off to the
    authenticator for the real decision (and, presumably, make all
    your security keys flash).

The second option doesn't seem terrible to me, and the first option leaves obvious room for future improvement.

Or for example, consider during the create account phase when acme.com<https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Facme.com&data=02%7C01%7Cvijaybh%40microsoft.com%7Ce8c9319e12f24c03caf308d4812b7cae%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636275471156232104&sdata=bo%2BZ6%2Fh07jMvaTTho7rnmZqN5IecCq%2B9CxLGcBMUVZ8%3D&reserved=0> tells the browser that it'll accept a username/password/oauth token from Google or Facebook or an Authenticator -- what does the browser draw then?  How does the user choose?

I think this boils down to the same question as above, with the slight twist that we're talking about sign-up rather than sign-in. Here, I agree with you that punting is a pretty reasonable option, as I don't think we've worked out a good story for sign-up with the existing credential types, much less new ones.

https://github.com/w3c/webappsec-credential-management/pull/72<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fw3c%2Fwebappsec-credential-management%2Fpull%2F72&data=02%7C01%7Cvijaybh%40microsoft.com%7Ce8c9319e12f24c03caf308d4812b7cae%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636275471156242112&sdata=AyRXhzuY2M3YrDekd2p2BhZd4YElzk4oqaYOqevLghU%3D&reserved=0> is something of a first step in this direction; aligning `Credential` object creation under a single, async constructor gives us a lot of room for future improvements.

We haven't figured out what it means to not require user mediation for webauthn, because there are lots of details.

The top of that response to Dirk's email that I mentioned earlier addresses some of his concern with `requireUserMediation()`, and tries to explain how I see it fitting into the story we'd tell developers around the various kinds of user-presence semantics y'all are discussing. Do my claims there make sense?

The relationships between user accounts and passwords is 1:1 -- but that's not the case for users and authenticators.

My understanding is that the relationship between users and public keys is 1:N: `mkwst@google.com<mailto:mkwst@google.com>` on `google.com<https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fgoogle.com%2F&data=02%7C01%7Cvijaybh%40microsoft.com%7Ce8c9319e12f24c03caf308d4812b7cae%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636275471156242112&sdata=P5lbcK685l4t5X9QzzysYw8j91Ga5OLTHnnUhG8c364%3D&reserved=0>` has a few security keys, all of which are valid for the account. The relationship between public keys and users, on the other hand, is 1:1: each of `mkwst@google.com<mailto:mkwst@google.com>`'s public keys for `google.com<https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fgoogle.com%2F&data=02%7C01%7Cvijaybh%40microsoft.com%7Ce8c9319e12f24c03caf308d4812b7cae%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636275471156242112&sdata=P5lbcK685l4t5X9QzzysYw8j91Ga5OLTHnnUhG8c364%3D&reserved=0>` is unique, and cannot be used to validate any other user.

It's the latter relationship that seems important here: just as the username/password credential unambiguously identifies a single relationship, so does the public key/assertion credential.

I can keep going,

Please do! I'd rather have your questions as known unknowns, rather than leaving the Rumsfeldian specter of unknown unknowns hanging over the discussion. :)

but the point is that there are questions here -- lots of them.  It will take a while to iron them out, to play with implementations, to iterate, to refactor, to make a UX that users understand.  On the other hand, we pretty much know how to build webauthn in its current form.  It's self-contained and doesn't depend on any outsides specs.

I agree with you that shipping the current spec is likely going to be faster than shipping something different than the current spec, if only because we haven't yet agreed upon what "different" means. :)

That said, I believe that the proposal in #384 is not that far off from what's in the current spec. The public API surface shifts in a number of ways, but I don't honestly think that the public API surface is where implementations are going to find most of the challenge. In Chrome's terms, I suspect that the Blink layer (IDL, bindings, etc) will be managable either way you go, while the //content layer changes will be more substantial. I think this is reflected in the PR: the IDL shifts quite a bit, while the attestation and assertion algorithms barely change at all.

Perhaps JC, Anthony, Angelo, etc can weigh in with their thoughts as vendors with existing (partial?) implementations?

If I understand the proposed merge correctly, it also requires that the credential management API be changed.  So now, before any webauthn api can be put out, the credential management API must be refactored and only then can webauthn be developed.  Also, let's not forget that there are websites that depend on the current credential management API.

I don't think this is the case. While putting together the PR that we're discussing, I did rewrite the credential management spec to refine and improve the extension points and internal algorithms, but the public API surface remained intact. The only visible change I can think of at the moment is the removal of the `SiteBoundCredential` intermediate interface, which seems like a good idea regardless.

The thought exercise of putting the PR together sparked some good discussion about additions that we could make to the API that would be good for existing developers (the `create()` proposal above is one), and clarifications that might likewise be useful in the status quo (the naming/structure of `unmediated`, for instance). These latter changes would make it easier to merge webauthn, to be sure, but they seem useful in themselves, and I expect we'll run with them regardless of the outcome of this discussion.

The PR is not the only possible credman merge proposal.  Here is another (if you don't like this one, we've got another):

I'm sorry; Ugh. This is a long email, and I haven't even gotten to your IDL yet. Rather than going line-by-line through it, I'll throw out some high-level opinions. At first glance, I think that splitting the top-level into `navigator.credentials.bearer` and `navigator.credentials.publicKey` feels a bit like the worst of both worlds. It conjoins two distinct APIs together through the use of a common noun ("credential"), but that noun seems to be a homograph: one side of the API uses "credential" to mean "the thing you give to the website in order to authenticate a user", while the other side uses "credential" as metadata adorning the actual authentication bits.

Contrast that with #384, which aims to unify the usage of "credential" by inverting the relationship between `ScopedCredential` and `AuthenticatorResponse`. Developers get a `Credential`, whatever API they call, and can send it up to the server for processing.

Perhaps more foundationally, though, this split makes it quite difficult to create a single entry-point to obtain credentials for a user, as we discussed above. Again, I see that as a clear selling point of the proposal you're countering.

Practically, as you noted above, there are websites that depend on the current credential management API. There are practical implications to pulling that API out from under existing users by moving `navigator.credentials.get()` to `navigator.credentials.bearer.get()`. It's painful for developers, and I think that kind of change needs more substantial justification than expedience. Ideally, we could avoid this kind of churn.

Regarding the claimed advantages:

1.  Size of change to existing APIs: It's not clear to me that this is a smaller change to webauthn than #384, and it's pretty clearly a substantially larger change to existing users of `navigator.credentials`.

2.  Store: I discussed `store()` a bit in the response to Dirk earlier this week: right in the middle of https://lists.w3.org/Archives/Public/public-webauthn/2017Apr/0147.html<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.w3.org%2FArchives%2FPublic%2Fpublic-webauthn%2F2017Apr%2F0147.html&data=02%7C01%7Cvijaybh%40microsoft.com%7Ce8c9319e12f24c03caf308d4812b7cae%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636275471156242112&sdata=kWpycGuw9%2BCQWZzzd3JsgtubSZ1s%2FtaENJCBdP7YBm8%3D&reserved=0>. I hope that clarifies the way I'm approaching it.

3.  Mediation: Likewise, this is the last piece of that email.

4.  Developers will only have to understand `credential`: This cuts both ways, as developers familiar with the credential management spec can't apply that knowledge to the new `publicKey` branch of the API, and in fact their existing experience will work against them due to the distinctions in usage of "credential".

5.  New methods can be added to `publicKey` without considering `bearer`: It's quite possible to hang methods off of a particular credential type if they only apply to a certain credential type. Moreover, I don't think this division actually removes the necessity to consider generalizing a given API, it just punts the question down the road. *shrug* I see this as a long-term drawback for short-term gain, in other words. :)

All that said, I'd like to pull out some points where I think we agree. Perhaps we can start with these smaller changes first:

1.  Allowing both attestations and assertions to derive from
    `AuthenticatorResponse` is a good idea. Let's extract this into
    something that we can merge on its own to improve the status quo.

2.  `PublicKeyCredential` is a better name than `ScopedCredential`!

3.  `PublicKeyCredential` inheriting from `Credential` (and therefore
    changing the types of both `id` and `type` properties) seems like
    a good step towards talking about the same thing when we say
    "credential".

All that is a somewhat negative note to end up on. Hrm. So instead, I'll say again that I appeciate the time y'all are spending on this with me, and I'm pretty confident that we'll end up with something better and cleaner than either of the proposals on the table through this discussion.

Thanks for your attention! Apologies for the length... I'll try to more agressively trim future responses. :)

-mike

Received on Wednesday, 12 April 2017 16:53:12 UTC