w3c / webauthn

Web Authentication: An API for accessing Public Key Credentials
https://w3c.github.io/webauthn/
Other
1.17k stars 168 forks source link

Surface platform authenticator status in the `create` (and maybe `get`) response / help RPs track UV/PA/RK #1567

Open lgarron opened 3 years ago

lgarron commented 3 years ago

The following are specified in the same place:

https://w3c.github.io/webauthn/#dictdef-authenticatorselectioncriteria

dictionary AuthenticatorSelectionCriteria {
    DOMString                    authenticatorAttachment;
    DOMString                    residentKey;
    boolean                      requireResidentKey = false;
    DOMString                    userVerification = "preferred";
};

However, there is no consistent way for the RP to check on these criteria:

Whether the registration is for a user-verifying authenticator

Embedded inside CBOR attestation.

Drawbacks:

Whether the registration is a discoverable credential (resident key)

Available in a client extension.

Drawbacks:

Whether the registration is a platform authenticator

As far as I can tell, this information is not available from the response. The RP has to ask for it, and hope the client did the right thing.

EDIT based on comments below: This is implicitly revealed by a value of internal returned by getTransports().


Looking at this, I have the following thoughts:

1) It would be nice to receive information whether the registration comes from a platform authenticator, at least in the case where the RP specifically asked for it. 2) It would be nice if this information was provided to the RP in a consistent way, and ideally in a way that the RP is likely to save by default (i.e. not purely in an extension).

I know there are historical reasons why the spec acts as it does. But it is bewildering to find out this information for an RP implementing WebAuthn the first time, and even I myself mistakenly believed for almost two years that the create response contains the platform authenticator status of the registration.

Quoting myself from https://github.com/w3c/webauthn/issues/1565

This breaks "avoid needless complexity" and — if it could be fixed in the spec — "priority of constituencies".

Since it looks like the spec will have at least 3 levels and level 2 is still being finalized, it is clear that browsers are still working on their WebAuthn implementations. I think it is still feasible to include a [change] at this point and hope for it to land in browsers in a reasonable time frame

lgarron commented 3 years ago

For what it's worth, my understanding is that authenticators can also change their properties over time. It would be nice to know for sure, and maybe to have a way for the RP to be able to tell if/when this happened. For example, updated info could be sent at auth time. However, this is not as useful for RPs if certain other features/bugs are addressed.

Kieun commented 3 years ago

Whether the registration is a platform authenticator As far as I can tell, this information is not available from the response. The RP has to ask for it, and hope the client did the right thing.

Regarding this issue, you can implicitly guess whether the generated credential is bound to the platform authenticator when returning the value as internal with getTransports call.

akshayku commented 3 years ago

Whether the registration is for a user-verifying authenticator

If RPs require user verification, they specify userVerification as required. RPs can always check for uv bit in the response to verify that user verification is performed.

Whether the registration is a discoverable credential (resident key)

The best we can do at this time is via the credProps extension. Regarding the implementation on one browser vs another, that is not a spec issue. Browser/OS vendors are teams with their own schedules and it always takes some time to get everything implemented. We will get there.

Whether the registration is a platform authenticator

API itself contains the attachment property. And the response has transports value.

lgarron commented 3 years ago

The best we can do at this time is via the credProps extension. Regarding the implementation on one browser vs another, that is not a spec issue.

I probably don't understand the internals well enough; what limits browsers from reporting if a discoverable credential was created?

Regarding this issue, you can implicitly guess whether the generated credential is bound to the platform authenticator when returning the value as internal with getTransports call.

API itself contains the attachment property. And the response has transports value.

Ah, thanks, i had forgotten about that. That leaves me with 2 thoughts:

1) How safe is it to assume that internal means platform authenticator? Do they mean the same thing, or can either refer to something that is not covered by the other? Could the spec provide a guarantee here?

2) If it's safe to include such data, is it desirable that the API only allows indirect access to authenticator UV/PA/RK, and using different opt-in mechanisms? As an RP implementer, I would expect to ask for those in one place, and receive info about them in one place.

As discussed in https://github.com/w3c/webauthn/issues/1556 , many devs will probably not collect such data until it's too late. We don't currently collect transport data for GitHub (I think it wasn't commonly available in browsers last we visited this), and doing so would entail 1) adding more code to webauthn-json for everyone, and 2) deciding where to check and store transport data.

It would be much more ergonomic if the value could be extracted from the default API response like user verification.

Kieun commented 3 years ago

I think the best effort for the attachment (transport) at this moment is asking for the specific attachment when creating the call by showing different UXs depending on the attachment for the user. And, that attachment value and returned value of getTransports for the future references should be stored. The detailed transport is just for RPs to help browsers to find the corresponding authenticators easily. If RP wants to do something with transport to decide UX flow, it's better idea to rely on attachment only (platform or cross-platform).

akshayku commented 3 years ago

How safe is it to assume that internal means platform authenticator?

"Internal" means platform authenticator. However, mobiles can also act like a roaming authenticator. So in that case, in addition to "internal", they will also include other transports. Overall it is a hint for the platform, and RP should store it and pass it back to the platform. However, they should not rely on exact implementation behavior, as those are actually hints.

is it desirable that the API only allows indirect access to authenticator UV/PA/RK, and using different opt-in mechanisms?

I would be against allowing certain authenticators and not others, if that's what you are asking. In a way, specifying attachment=platform property limits one to platform authenticators, but that was for a special case for registration. For authentication, intentionally, there is no attachment property as a platform can be interacted via other mechanisms.

nsatragno commented 3 years ago

what limits browsers from reporting if a discoverable credential was created?

That's exactly what credProps does!

equalsJeffH commented 3 years ago

on 2021-02-10 call: @ve7jtb summarizes that this is begging the question of having a hybrid call, e.g.:pass in known credIDs, and create new one if those don't work (ie yield an assertion): "assert or create". (perhaps that is more what issue #1568 is about)

In any case we are uncertain of the motivation behind this.

@nicksteele will ask for clarification.

equalsJeffH commented 3 years ago

Summarizing: there are (admittedly imperfect) answers to all three of the original post's "criteria" in the above discussion. Additionally, the RP techniques and webauthn API changes proposed in issue #1637 will (we hope) ameliorate the concerns expressed in this issue.

emlun commented 1 week ago

I would argue that most of these are addressed at this point:

Whether the registration is for a user-verifying authenticator

This is now sort-of available via getAuthenticatorData() followed by a static byte index ([32]) and bitmask (& 0b100), no CBOR library needed. Only if the RP requests userVerification: "preferred" or "required", but maybe that's close enough.

Whether the registration is a discoverable credential (resident key)

As mentioned above, this is available in the credProps extension output.

Whether the registration is a platform authenticator

[...]

  1. It would be nice to receive information whether the registration comes from a platform authenticator, at least in the case where the RP specifically asked for it.

This is now available as the PublicKeyCredential.authenticatorAttachment attribute.

  1. It would be nice if this information was provided to the RP in a consistent way, and ideally in a way that the RP is likely to save by default (i.e. not purely in an extension).

Not really addressed. Perhaps L4 could move credProps.rk to a property on AuthenticatorAttestationResponse, like getTransports(), but on the other hand that would also just mean there's yet another place the RP needs to look for this information.

  1. It would be nice if all three properties were attested by the authenticator. I recognize this is probably a stretch.

Not addressed. I personally don't think these properties are important enough to be worth this effort.