Webauthn: Clarify relationships between "uv"/"up" of the CTAP spec and "userVerification"/"userPresence"

Created on 18 Dec 2018  路  5Comments  路  Source: w3c/webauthn

In the CTAP spec (https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html), we have the following tables:

WebAuthN authenticatorMakeCredentialoperation | CTAP聽authenticatorMakeCredential聽operation
--- | ---
requireUserPresence | Not present in the current version of CTAP. Authenticators are assumed to always check user presence.
requireUserVerification | options.uv or pinAuth/pinProtocol

WebAuthN聽authenticatorGetAssertion聽operation | CTAP聽authenticatorGetAssertion聽operation
--- | ---
requireUserPresence | options.up
requireUserVerification | options.uv or pinAuth/pinProtocol

That to me means userVerification/userPresence = uv/up.

Then we have this in the spec: https://www.w3.org/TR/webauthn/#getAssertion

Let _userPresence_ be a Boolean value set to the inverse of _userVerification_.

I interpret this sentence as userVerification includes userPresence. When userVerification is required, userPresence is also required implicitly. Hence, the response from the authenticator will only have the following two valid combinations between uv and up ({uv, up}):

  • {1, 1}
  • {0, 1}

However, in the CTAP spec, it looks like requiring uv doesn't necessary mean requiring up.
In section 5.2, Step 7:

Collect user consent if required. This step MUST happen before the following steps due to privacy reasons (i.e., authenticator cannot disclose existence of a credential until the user interacted with the device):

  • If the "uv" option was specified and set to true:

    • If device doesn鈥檛 support user-identifiable gestures, return the CTAP2_ERR_UNSUPPORTED_OPTION error.

    • Collect a user-identifiable gesture. If gesture validation fails, return the CTAP2_ERR_OPERATION_DENIED error.

  • If the "up" option was specified and set to true, collect the user鈥檚 consent.

    • If no consent is obtained and a timeout occurs, return the CTAP2_ERR_OPERATION_DENIED error.

I interpret the above as the authenticator will check uv and up independently according to the request's parameters.

If user agents send the request as suggested by both spec when userVerification is required from the RP, then an authenticator could send a response that includes the {uv, up} as {1, 0}.

So this really confuses me. I think we need some clarifications on either the WebAuthN spec or the CTAP spec. I will suggest we change the WebAuthN spec to:
"Let _userPresence_ be a Boolean value set to the inverse of _userVerification_." => "Let _userPresence_ be true."

pr-open CTAP algorithmWebIDL technical

Most helpful comment

I agree this is suboptimal as currently written. As I recall, the construction of "Let _userPresence_ be a Boolean value set to the inverse of _userVerification_" was done in order to align WebAuthn with CTAP and get the desired behaviour, but looking back now at the CTAP archives it seems like I might just have misinterpreted those CTAP consent collection steps as exclusive branches instead of sequential steps.

I will suggest we change the WebAuthN spec to:
"Let _userPresence_ be a Boolean value set to the inverse of _userVerification_." => "Let _userPresence_ be true."

I support this suggestion, but I think we probably can't do this before L2.

All 5 comments

I agree this is suboptimal as currently written. As I recall, the construction of "Let _userPresence_ be a Boolean value set to the inverse of _userVerification_" was done in order to align WebAuthn with CTAP and get the desired behaviour, but looking back now at the CTAP archives it seems like I might just have misinterpreted those CTAP consent collection steps as exclusive branches instead of sequential steps.

I will suggest we change the WebAuthN spec to:
"Let _userPresence_ be a Boolean value set to the inverse of _userVerification_." => "Let _userPresence_ be true."

I support this suggestion, but I think we probably can't do this before L2.

While the text would benefit from some clarification about the terms, here is the situation.

Basic principles:

  • User presence is ALWAYS required from the WebAuthN spec. Silent authentication is NOT allowed as per the spec.
  • RP can influence where it requires user verification from the authenticator.

    • There are three user verification modes RP can request:



      • Required: Client/platform must fail such request if authenticator is not capable of doing user verification.


      • Preferred: Client/platform will try to get the user verification if possible, but will not fail if authenticator is not capable of doing user verification.


      • Discouraged: Client will try to get the user presence only if possible. If not possible, client will also get user verification. For example, certain authenticators can only allow operations on their authenticator if user verification is performed. It's that authenticators decision. Another example is during MakeCredential, if authenticator is protected, currently, its required to verify the user.



CTAP options that influence user presence:

  • up: check for user presence

CTAP options that influence user verification:

  • uv: check for built-in user verification method
  • pinAuth/pinProtocol: Do the user verification using pinToken.

_So the only option RP can influence from WebAuthN is "UserVerificationRequirement" which is applicable for both webauthn create and get methods and controls user verification. User presence is always required from WebAuthN layer._

So below is the WebAuthN options that RP translates to CTAP: _In every case below, the actual request that is being sent to the authenticator (and whose response will be send back to the RP) MUST have "up" set to true as silent authentication is NOT allowed from the spec currently and user presence is always required._

  • _WebAuthN Method: Create_

    • UserVerificationRequirement: Required/Preferred:

      • _Authenticator state: Not protected either by PIN or by built in method_

        • Platform/Client can try to set the PIN, provision fingerprint inline if authenticator is capable of it. However, if this cannot be done, then Client MUST fail the request.

      • _Authenticator state: protected by PIN_

        • Final request options: _"up" = true, pinProtocol = 1, pinAuth = _

      • _Authenticator state: protected by built in user verification method such as fingerprint._

        • Final request options: _"up" = true, "uv" = true_

      • _Authenticator state: protected by both PIN as well as built in user verification method._

        • Client/platform is free to choose any method. One strategy can be that first try built in user verification method, and if that doesn't succeed for some reason, try PIN.

    • UserVerificationRequirement: discouraged:

      • _Authenticator state: Not protected either by PIN or by built in method_

        • Final request options: _"up = true"_

      • _Authenticator state: protected by PIN_

        • Important point as of current CTAP spec: Authenticator required user verification for makecredential if authenticator is protected. So WebAuthN choice can't degrade authenticator security currently.

        • Final request options: _"up" = true, pinProtocol = 1, pinAuth = _

      • _Authenticator state: protected by built in user verification method such as fingerprint._

        • Final request options: _"up" = true, "uv" = true_

      • _Authenticator state: protected by both PIN as well as built in user verification method._

        • Client/platform is free to choose any method. One strategy can be that first try built in user verification method, and if that doesn't succeed for some reason, try PIN.

  • _WebAuthN Method: Get_

    • UserVerificationRequirement: Required/Preferred:

      • _Authenticator state: Not protected either by PIN or by built in method_

        • Platform/Client can try to set the PIN, provision fingerprint inline if authenticator is capable of it. However, if this cannot be done, then Client MUST fail the request.

      • _Authenticator state: protected by PIN_

        • This is reflected in authenticatorGetInfo via "ClientPIN" set to true. If ClientPIN is set to false, that means that authenticator is capable of being protected by the PIN but, it's not being configured yet.

        • Client gathers PIN from the user and then uses pinAuth/pinProtocol to send that information to the authenticator. To protect from cached information on the client, up=true MUST be set.

        • Final request options: _"up" = true, pinProtocol = 1, pinAuth = _

      • _Authenticator state: protected by built in user verification method such as fingerprint._

        • Whether authenticator is protected by built in user verification method is revealed by authenticaorGetInfo where uv is set to true. If "uv" is set to false, that means that authenticator is capable of user verification but its not configured yet.

        • Final request options: _"up" = true, "uv" = true _

      • _Authenticator state: protected by both PIN as well as built in user verification method._

        • Client/platform is free to choose any method. One strategy can be that first try built in user verification method, and if that doesn't succeed for some reason, try PIN.

    • UserVerificationRequirement: discouraged:

      • _Authenticator state: Not protected either by PIN or by built in method_

        • Final request options: _"up = true"_

      • _Authenticator state: protected by PIN_

        • Final request options: _"up" = true_

      • _Authenticator state: protected by built in user verification method such as fingerprint._

        • Final request options: _"up" = true_

      • _Authenticator state: protected by both PIN as well as built in user verification method._

        • Final request options: _"up" = true_

I also agree with Emil and alanwaketan. This should be changed to "Let userPresence be true"

I think we want a substantial WG discussion of this before we foreclose the possibility of silent authentication in some circumstances. Particularly, silent authentication without user presence may be appropriate for device authentication in IoT applications.

wrt @selfissued's https://github.com/w3c/webauthn/issues/1123#issuecomment-460800238:

to try to clarify and set context: not supporting "silent authn" (i.e., a webauthn authn ceremony lacking any user interaction) in webauthn (i.e., "on the _Web_" specifically, i.e., above the authenticator API (e.g., CTAP) layer) has historically been justified on a _privacy_ basis. See the discussion regarding use cases and issues here, and here, and here from issue #199.

AFAICT, CTAP presently implicitly supports so-called "silent authentication" if authenticatorGetAssertion is called with both uv=false and up=false.

What might be the IOT-specific use cases ? Might they be addressed at the authenticator API level (e.g., CTAP) and not at the Web level?

Was this page helpful?
0 / 5 - 0 ratings