Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates based on DOM's abort reason #1706

Merged
merged 9 commits into from
May 18, 2022
71 changes: 32 additions & 39 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1546,7 +1546,7 @@ When this method is invoked, the user agent MUST execute the following algorithm

1. Assert: <code>|options|.{{CredentialCreationOptions/publicKey}}</code> is present.

1. If <var ignore>sameOriginWithAncestors</var> is [FALSE], return a "{{NotAllowedError}}" {{DOMException}}.
1. If <var ignore>sameOriginWithAncestors</var> is [FALSE], throw a "{{NotAllowedError}}" {{DOMException}}.

Note: This "sameOriginWithAncestors" restriction aims to address a tracking concern raised in [Issue #1336](https://github.com/w3c/webauthn/issues/1336). This may be revised in future versions of this specification.

Expand All @@ -1571,14 +1571,13 @@ When this method is invoked, the user agent MUST execute the following algorithm

Note: The user agent should take cognitive guidelines into considerations regarding timeout for users with special needs.

1. If the length of <code>|options|.{{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialUserEntity/id}}</code> is not between 1 and 64 bytes (inclusive) then return a {{TypeError}}.
1. If the length of <code>|options|.{{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialUserEntity/id}}</code> is not between 1 and 64 bytes (inclusive) then throw a {{TypeError}}.

1. Let |callerOrigin| be {{PublicKeyCredential/[[Create]](origin, options, sameOriginWithAncestors)/origin}}. If |callerOrigin| is an [=opaque origin=], return a {{DOMException}} whose name is
"{{NotAllowedError}}", and terminate this algorithm.
1. Let |callerOrigin| be {{PublicKeyCredential/[[Create]](origin, options, sameOriginWithAncestors)/origin}}. If |callerOrigin| is an [=opaque origin=], throw a "{{NotAllowedError}}" {{DOMException}}.

1. Let |effectiveDomain| be the |callerOrigin|'s [=effective domain=].
If [=effective domain=] is not a [=valid domain=], then return a
{{DOMException}} whose name is "{{SecurityError}}" and terminate this algorithm.
If [=effective domain=] is not a [=valid domain=], then throw a
"{{SecurityError}}" {{DOMException}}.

Note: An [=effective domain=] may resolve to a [=host=], which can be represented in various manners,
such as [=domain=], [=ipv4 address=], [=ipv6 address=], [=opaque host=], or [=empty host=].
Expand All @@ -1596,8 +1595,7 @@ a numbered step. If outdented, it (today) is rendered as a bullet in the midst o

: is present
:: If <code>|options|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> [=is not a
registrable domain suffix of and is not equal to=] |effectiveDomain|, return a {{DOMException}} whose name
is "{{SecurityError}}", and terminate this algorithm.
registrable domain suffix of and is not equal to=] |effectiveDomain|, throw a "{{SecurityError}}" {{DOMException}}.

: Is not present
:: Set <code>|options|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> to
Expand Down Expand Up @@ -1630,8 +1628,7 @@ a numbered step. If outdented, it (today) is rendered as a bullet in the midst o
1. [=list/Append=] the pair of <code>|current|.{{PublicKeyCredentialParameters/type}}</code> and |alg| to
|credTypesAndPubKeyAlgs|.

If |credTypesAndPubKeyAlgs| [=list/is empty=], return a {{DOMException}} whose name is
"{{NotSupportedError}}", and terminate this algorithm.
If |credTypesAndPubKeyAlgs| [=list/is empty=], throw a "{{NotSupportedError}}" {{DOMException}}.
</dl>

1. Let |clientExtensions| be a new [=map=] and let |authenticatorExtensions| be a new [=map=].
Expand Down Expand Up @@ -1665,9 +1662,8 @@ a numbered step. If outdented, it (today) is rendered as a bullet in the midst o

1. Let |clientDataHash| be the [=hash of the serialized client data=] represented by |clientDataJSON|.

1. If the <code>|options|.{{CredentialCreationOptions/signal}}</code> is present and its
[=AbortSignal/aborted flag=] is set to [TRUE], return a {{DOMException}} whose name is "{{AbortError}}"
and terminate this algorithm.
1. If <code>|options|.{{CredentialCreationOptions/signal}}</code> is present and [=AbortSignal/aborted=], throw
the <code>|options|.{{CredentialCreationOptions/signal}}</code>'s [=AbortSignal/abort reason=].

1. Let |issuedRequests| be a new [=ordered set=].

Expand All @@ -1689,13 +1685,12 @@ 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|. Return a {{DOMException}} whose name is "{{NotAllowedError}}".
and [=set/remove=] |authenticator| from |issuedRequests|. Throw a "{{NotAllowedError}}" {{DOMException}}.

: If the <code>|options|.{{CredentialCreationOptions/signal}}</code> is present and its
[=AbortSignal/aborted flag=] is set to [TRUE],
: If <code>|options|.{{CredentialCreationOptions/signal}}</code> is present and [=AbortSignal/aborted=],
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=]
operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. Then return a {{DOMException}}
whose name is "{{AbortError}}" and terminate this algorithm.
operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. Then throw the
<code>|options|.{{CredentialCreationOptions/signal}}</code>'s [=AbortSignal/abort reason=].
emlun marked this conversation as resolved.
Show resolved Hide resolved

: If an |authenticator| becomes available on this [=client device=],
:: Note: This includes the case where an |authenticator| was available upon |lifetimeTimer| initiation.
Expand Down Expand Up @@ -1842,7 +1837,7 @@ a numbered step. If outdented, it (today) is rendered either as a bullet in the
:: 1. [=set/Remove=] |authenticator| from |issuedRequests|.
1. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on
|authenticator| and [=set/remove=] it from |issuedRequests|.
1. Return a {{DOMException}} whose name is "{{InvalidStateError}}" and terminate this algorithm.
1. Throw an "{{InvalidStateError}}" {{DOMException}}.

Note: This error status is handled separately because the |authenticator| returns it only if
|excludeCredentialDescriptorList| identifies a credential [=bound credential|bound=] to the |authenticator| and the user has [=user
Expand Down Expand Up @@ -1944,7 +1939,7 @@ a numbered step. If outdented, it (today) is rendered either as a bullet in the

</dl>

1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". In order to prevent information leak that could identify the
1. Throw a "{{NotAllowedError}}" {{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.

Expand Down Expand Up @@ -2037,11 +2032,11 @@ When this method is invoked, the user agent MUST execute the following algorithm
Note: The user agent should take cognitive guidelines into considerations regarding timeout for users with special needs.

1. Let |callerOrigin| be {{PublicKeyCredential/[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)/origin}}. If |callerOrigin| is
an [=opaque origin=], return a {{DOMException}} whose name is "{{NotAllowedError}}", and terminate this algorithm.
an [=opaque origin=], throw a "{{NotAllowedError}}" {{DOMException}}.

1. Let |effectiveDomain| be the |callerOrigin|'s [=effective domain=].
If [=effective domain=] is not a [=valid domain=], then return a
{{DOMException}} whose name is "{{SecurityError}}" and terminate this algorithm.
If [=effective domain=] is not a [=valid domain=], then throw a
"{{SecurityError}}" {{DOMException}}.

Note: An [=effective domain=] may resolve to a [=host=], which can be represented in various manners,
such as [=domain=], [=ipv4 address=], [=ipv6 address=], [=opaque host=], or [=empty host=].
Expand All @@ -2056,8 +2051,7 @@ When this method is invoked, the user agent MUST execute the following algorithm
Otherwise:

1. If |options|.{{PublicKeyCredentialRequestOptions/rpId}} [=is not a registrable domain suffix of and is not
equal to=] |effectiveDomain|, return a {{DOMException}} whose name is "{{SecurityError}}", and terminate
this algorithm.
equal to=] |effectiveDomain|, throw a "{{SecurityError}}" {{DOMException}}.

1. Set |rpId| to |options|.{{PublicKeyCredentialRequestOptions/rpId}}.

Expand Down Expand Up @@ -2097,9 +2091,8 @@ When this method is invoked, the user agent MUST execute the following algorithm

1. Let |clientDataHash| be the [=hash of the serialized client data=] represented by |clientDataJSON|.

1. If the <code>|options|.{{CredentialRequestOptions/signal}}</code> is present and its
[=AbortSignal/aborted flag=] is set to [TRUE], return a {{DOMException}} whose name is "{{AbortError}}"
and terminate this algorithm.
1. If <code>|options|.{{CredentialRequestOptions/signal}}</code> is present and [=AbortSignal/aborted=], throw
the <code>|options|.{{CredentialRequestOptions/signal}}</code>'s [=AbortSignal/abort reason=].

1. Let |issuedRequests| be a new [=ordered set=].

Expand All @@ -2125,16 +2118,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|. Return a {{DOMException}} whose name is "{{NotAllowedError}}".
and [=set/remove=] |authenticator| from |issuedRequests|. Throw a "{{NotAllowedError}}" {{DOMException}}.

: If the {{CredentialRequestOptions/signal}} member is present and the [=AbortSignal/aborted flag=] is set to
[TRUE],
: If <code>|options|.{{CredentialRequestOptions/signal}}</code> is present and [=AbortSignal/aborted=],
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
and [=set/remove=] |authenticator| from |issuedRequests|. Then
return a {{DOMException}} whose name is "{{AbortError}}" and terminate this algorithm.
throw the <code>|options|.{{CredentialRequestOptions/signal}}</code>'s [=AbortSignal/abort reason=].

: If |issuedRequests| is empty, <code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> is not empty, and no |authenticator| will become available for any [=public key credentials=] therein,
:: Indicate to the user that no eligible credential could be found. When the user acknowledges the dialog, return a {{DOMException}} whose name is "{{NotAllowedError}}".
:: Indicate to the user that no eligible credential could be found. When the user acknowledges the dialog, throw a "{{NotAllowedError}}" {{DOMException}}.

Note: One way a [=client platform=] can determine that no |authenticator| will become available is by examining the <code>{{transports}}</code> members of the present <code>{{PublicKeyCredentialDescriptor}}</code> [=list/items=] of <code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code>, if any. For example, if all <code>{{PublicKeyCredentialDescriptor}}</code> [=list/items=] list only <code>{{AuthenticatorTransport/internal}}</code>, but all [=platform authenticator|platform=] |authenticator|s have been tried, then there is no possibility of satisfying the request. Alternatively, all <code>{{PublicKeyCredentialDescriptor}}</code> [=list/items=] may list <code>{{transports}}</code> that the [=client platform=] does not support.

Expand Down Expand Up @@ -2317,7 +2309,7 @@ When this method is invoked, the user agent MUST execute the following algorithm
1. Return |constructAssertionAlg| and terminate this algorithm.
</dl>

1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". In order to prevent information leak that could identify the
1. Throw a "{{NotAllowedError}}" {{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.

Expand All @@ -2331,7 +2323,7 @@ authorizing an authenticator with which to complete the operation.
<div link-for-hint="PublicKeyCredential/[[Store]](credential, sameOriginWithAncestors)">

The <dfn for="PublicKeyCredential" method>\[[Store]](credential, sameOriginWithAncestors)</dfn> method is not supported
for Web Authentication's {{PublicKeyCredential}} type, so it always returns an error.
for Web Authentication's {{PublicKeyCredential}} type, so it always throws an error.

Note: This algorithm is synchronous; the {{Promise}} resolution/rejection is handled by
{{CredentialsContainer/store()|navigator.credentials.store()}}.
Expand All @@ -2349,7 +2341,7 @@ This [=internal method=] accepts two arguments:

When this method is invoked, the user agent MUST execute the following algorithm:

1. Return a {{DOMException}} whose name is "{{NotSupportedError}}", and terminate this algorithm
1. Throw a "{{NotSupportedError}}" {{DOMException}}.

</div>

Expand Down Expand Up @@ -2993,11 +2985,11 @@ Developers are encouraged to leverage the {{AbortController}} to manage the
See [[dom#abortcontroller-api-integration]] section for detailed instructions.

Note: [[dom#abortcontroller-api-integration]] section specifies that web platform APIs integrating with the
{{AbortController}} must reject the promise immediately once the [=AbortSignal/aborted flag=] is set.
{{AbortController}} must reject the promise immediately once the {{AbortSignal}} is [=AbortSignal/aborted=].
Given the complex inheritance and parallelization structure of the {{PublicKeyCredential/[[Create]](origin, options, sameOriginWithAncestors)}}
and {{PublicKeyCredential/[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)}} methods, the algorithms for the two APIs fulfills this
requirement by checking the [=AbortSignal/aborted flag=] in three places. In the case of
{{PublicKeyCredential/[[Create]](origin, options, sameOriginWithAncestors)}}, the aborted flag is checked first in
requirement by checking the [=AbortSignal/aborted=] property in three places. In the case of
{{PublicKeyCredential/[[Create]](origin, options, sameOriginWithAncestors)}}, the [=AbortSignal/aborted=] property is checked first in
[[credential-management-1#algorithm-create]] immediately before calling {{Credential/[[Create]](origin, options, sameOriginWithAncestors)}},
then in [[#sctn-createCredential]] right before [=authenticator sessions=] start, and finally
during [=authenticator sessions=]. The same goes for
Expand Down Expand Up @@ -7219,6 +7211,7 @@ Julien Cayzac,
Domenic Denicola,
Rahul Ghosh,
Brad Hill,
Nidhi Jaju,
Jing Jin,
Wally Jones,
Ian Kilpatrick,
Expand Down