Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 67 additions & 8 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1913,7 +1913,15 @@ a numbered step. If outdented, it (today) is rendered as a bullet in the midst o

: If the user exercises a user agent user-interface option to cancel the process,
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
and [=set/remove=] |authenticator| from |issuedRequests|. Throw a "{{NotAllowedError}}" {{DOMException}}.
and [=set/remove=] |authenticator| from |issuedRequests|.

If the user agent is informing the user that
the last used |authenticator| cannot collect [=user verification=] when
<code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/userVerification}}</code>
is set to {{UserVerificationRequirement/required}},
throw a "{{UserVerificationError}}" {{DOMException}}.
Comment on lines +1918 to +1922
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The equivalent error on the authenticator layer is error code equivalent to "ConstraintError", so I think that could be used here too?

This would lump this together with another ConstraintError thrown when authenticatorSelection.userVerification == "required" and mediation == "conditional", but that is also an error expressing that UV was required but couldn't be performed, so I think that can be okay?

Then we could also add a case to pass through error code equivalent to "ConstraintError" from the authenticator layer, like we do with InvalidStateError.

Copy link
Contributor Author

@MasterKale MasterKale Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming back to this comment, ConstraintError is currently used to communicate a couple of issues during registration:

  • A resident key was required but the authenticator doesn't support it
  • UV was required but the authenticator couldn't collect it

I'm kinda bummed out by the prospect of mashing "no rkey support" and "can't do UV" into the same bucket, even though I have to admit it'd make sense to make the change you suggest and turn this proposed UserVerificationError into a ConstraintError because an existing similar error state already sets precedent.

We're probably well into the time where lack of rkey support is the minority cause of a ConstraintError; put another way, my concern may not hold as much water because the current state of passkeys will have RPs implying that a ConstraintError is more likely "can't do UV" than "can't create an rkey."

I'd like to discuss this at the next WG meeting before I make any changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open question: can we define specific values for a DOMException's message when we define an error to throw? For example, could we define e.g. "throw a ConstraintError with message set to "UV required but authenticator did not support UV"" to throw RP's a bone here if we standardized on using an existing error?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... it looks like we can!

WebIDL §2.8 Exceptions reads:

An example of including additional information used to construct the exception message would be:

Throw a "SyntaxError" DOMException indicating that the given value had disallowed trailing spaces.

This refers to one of the steps in §3.14.3. Creating and throwing exceptions which is linked just afterwards:

To create a DOMException given a string name:
[...]
4. Set ex’s message to an implementation-defined message appropriate for the exceptional situation. The calling specification may contain information to to help implementations construct this message.
Implementations need to be cautious not to leak sensitive or secured information when constructing this message, e.g., by including the URL of a cross-origin frame, or information which could identify the user.

2.8.1. Base DOMException error names does state that "When creating or throwing a DOMException, specifications must use one of these names [listed in the DOMException names table].", but I can't see anything like that for message.

So yes, I think it seems like "The calling specification [WebAuthn] may contain information to to help implementations construct [ex's message]".


Otherwise, throw an "{{OptOutError}}" {{DOMException}}.

: If <code>|options|.{{CredentialCreationOptions/signal}}</code> is present and [=AbortSignal/aborted=],
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=]
Expand Down Expand Up @@ -2181,7 +2189,9 @@ a numbered step. If outdented, it (today) is rendered as a bullet in the midst o
</dl>
</li>

1. Throw a "{{NotAllowedError}}" {{DOMException}}.
1. Throw a "{{TimeoutError}}" {{DOMException}}. In order to prevent information leak that could identify the
user without [=user consent|consent=], this step MUST NOT be executed before |lifetimeTimer| has expired. See
[[#sctn-make-credential-privacy]] for details.

During the above process, the user agent SHOULD show some UI to the user to guide them in the process of selecting and
authorizing an authenticator. When <code>|options|.{{CredentialCreationOptions/mediation}}</code> is set to {{CredentialMediationRequirement/conditional}}, prominent modal UI should <i>not</i> be shown <i>unless</i> credential creation was previously consented to via means determined by the user agent.
Expand Down Expand Up @@ -2225,9 +2235,15 @@ The following {{DOMException}} exceptions can be raised:
the [=client=] does not support [[#sctn-related-origins|related origin requests]]
or the [$related origins validation procedure$] failed.

: {{TimeoutError}}
:: The ceremony was cancelled by the user agent after exceeding the time limit permitted for the ceremony.
See [[#sctn-timeout-recommended-range]] for more information.

: {{UserVerificationError}}
:: The user was unable to complete [=user verification=] as required by the [=[RP]=].

: {{NotAllowedError}}
:: A catch-all error covering a wide range of possible reasons,
including common ones like the user canceling out of the ceremony.
:: A catch-all error covering a wide range of possible reasons.
Some of these causes are documented throughout this spec,
while others are client-specific.

Expand Down Expand Up @@ -2450,7 +2466,15 @@ When this method is invoked, the user agent MUST execute the following algorithm

: If the user exercises a user agent user-interface option to cancel the process,
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
and [=set/remove=] |authenticator| from |issuedRequests|. Throw a "{{NotAllowedError}}" {{DOMException}}.
and [=set/remove=] |authenticator| from |issuedRequests|.

If the user agent is informing the user that
the last used |authenticator| cannot collect [=user verification=] when
<code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/userVerification}}</code>
is set to {{UserVerificationRequirement/required}},
throw a "{{UserVerificationError}}" {{DOMException}}.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have to replace the UserVerificationError during registration with ConstraintError, then we'll have to replace this one during authentication as well.


Otherwise, throw an "{{OptOutError}}" {{DOMException}}.

: If <code>|options|.{{CredentialRequestOptions/signal}}</code> is present and [=AbortSignal/aborted=],
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
Expand Down Expand Up @@ -2629,7 +2653,9 @@ When this method is invoked, the user agent MUST execute the following algorithm
1. Return |pubKeyCred| and terminate this algorithm.
</dl>

1. Throw a "{{NotAllowedError}}" {{DOMException}}.
1. Throw a "{{TimeoutError}}" {{DOMException}}. In order to prevent information leak that could identify the
user without [=user consent|consent=], this step MUST NOT be executed before |lifetimeTimer| has expired. See
[[#sctn-assertion-privacy]] for details.

</div>

Expand Down Expand Up @@ -2782,9 +2808,15 @@ The following {{DOMException}} exceptions can be raised:
the [=client=] does not support [[#sctn-related-origins|related origin requests]]
or the [$related origins validation procedure$] failed.

: {{TimeoutError}}
:: The ceremony was cancelled by the user agent after exceeding the time limit permitted for the ceremony.
See [[#sctn-timeout-recommended-range]] for more information.

: {{UserVerificationError}}
:: The user was unable to complete [=user verification=] as required by the [=[RP]=].

: {{NotAllowedError}}
:: A catch-all error covering a wide range of possible reasons,
including common ones like the user canceling out of the ceremony.
:: A catch-all error covering a wide range of possible reasons.
Some of these causes are documented throughout this spec,
while others are client-specific.
</dl>
Expand Down Expand Up @@ -3952,6 +3984,33 @@ should continue. When the {{Window}} object associated with the [=Document=] los
SHOULD be aborted.


## WebAuthn Interfaces ## {#sctn-interfaces}

The subection below defines custom interfaces used throughout WebAuthn.

### Custom WebAuthn Exceptions ### {#iface-custom-webauthn-exceptions}

For descriptions of these exceptions,
please see [[#sctn-create-request-exceptions]] and [[#sctn-get-request-exceptions]].

<xmp class="idl">
[Exposed=Window, Serializable]
interface UserVerificationError : DOMException {
constructor(optional DOMString message = "");
};
</xmp>

The <code>new UserVerificationError(|message|)</code> constructor steps are:

1. Set [=this=]'s {{DOMException/name}} to `"UserVerificationError"`.
1. Set [=this=]'s {{DOMException/message}} to `message`.

{{UserVerificationError}} objects are [=serializable objects=].

Their [=serialization steps=], given |value| and |serialized|, are to run the {{DOMException}} [=serialization steps=] given |value| and |serialized|.

Their [=deserialization steps=], given |serialized| and |value|, are to run the {{DOMException}} [=deserialization steps=] given |serialized| and |value|.

## WebAuthn Extensions Inputs and Outputs ## {#sctn-extensions-inputs-outputs}

The subsections below define the data types used for conveying [=WebAuthn extension=] inputs and outputs.
Expand Down