Skip to content

Commit 931b46e

Browse files
Angelo LiaoequalsJeffH
authored andcommitted
Make create() and get() abortable (#544)
* do not call authenticatorMakeCredential() with separate |rpId| fixes #466 * credID returned by authnrGetAssn() is optional if allowCreds has exactly 1 member fixes #472 * fixup global object reference per domenic, improves #472 * indent 4.1.4 step 18et al to clarify relation to prior step * fix line indent * do not call authenticatorMakeCredential() with separate |rpId| fixes #466 * credID returned by authnrGetAssn() is optional if allowCreds has exactly 1 member fixes #472 * fixup global object reference per domenic, improves #472 * indent 4.1.4 step 18et al to clarify relation to prior step * fix line indent * post rebase-on-master, fix dangling MakeCredentialOptions * fix error in resolving rebase conflicts * further rebase conflict resolution error fixups * convert switch steps to colon-denotation * tag 'while' * primary changes for improving #472 mostly complete * further issue #472 cleanups * del 'cancel the timer' from #creatCredential fixes #535 * polish constructResultantCredentialCallback method description * marked authenticator model section as non-normative * marked relying party operation section as non-normative * fix proper subset tweak * Added abort signal object and steps to webauthn * fixed a minor issue with linking * add minor edits to focus on the main things * getting the blank line correct * Added a example section to explain how abort should be used * fix up example * committing before computer dies * updated grammars of the example based on feedback * update example text * Updated with the section on switching tab; complete the PR * minor tweak * finished polishing the spec * whoops one leftover * finally figured out how to remove last two linking errors * take out abortsignal from extension; edit promise rejection
1 parent 7153b55 commit 931b46e

File tree

1 file changed

+97
-3
lines changed

1 file changed

+97
-3
lines changed

index.bs

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,20 @@ spec: credential-management-1; urlPrefix: https://w3c.github.io/webappsec-creden
9191
for: CredentialsContainer
9292
type: method
9393
text: create(); url: dom-credentialscontainer-create
94+
type: dfn
95+
text: signal
9496

9597
spec: mixed-content; urlPrefix: www.w3.org/TR/mixed-content/
9698
type: dfn
9799
text: a priori authenticated
100+
101+
spec: page-visibility; urlPrefix: https://www.w3.org/TR/page-visibility/
102+
type: dfn
103+
text: visibility states
104+
105+
spec: WHATWG HTML; urlPrefix: https://html.spec.whatwg.org/
106+
type: dfn
107+
text: focus
98108
</pre> <!-- class=anchors -->
99109

100110
<pre class="link-defaults">
@@ -619,7 +629,9 @@ To support obtaining assertions via {{CredentialsContainer/get()|navigator.crede
619629
{{CredentialsContainer/create()|navigator.credentials.create()}} to request the creation of a new [=credential key pair=]
620630
and {{PublicKeyCredential}}, managed by an [=authenticator=].
621631
On success, the returned {{promise}} will be resolved with a {{PublicKeyCredential}} containing an
622-
{{AuthenticatorAttestationResponse}} object.
632+
{{AuthenticatorAttestationResponse}} object. This {{CredentialsContainer/create()|navigator.credentials.create()}}
633+
operation can be aborted by leveraging the {{AbortController}}; see
634+
[[dom#abortcontroller-api-integration]] for detailed instructions.
623635

624636
Note: This algorithm is synchronous; the {{Promise}} resolution/rejection is handled by
625637
{{CredentialsContainer/create()|navigator.credentials.create()}}.
@@ -731,6 +743,10 @@ When this method is invoked, the user agent MUST execute the following algorithm
731743

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

746+
1. If the <code>|options|.{{CredentialCreationOptions/signal}}</code> is [=present=] and its
747+
[=AbortSignal/aborted flag=] is set to true, return a {{DOMException}} whose name is "{{AbortError}}"
748+
and terminate this algorithm.
749+
734750
1. Start |lifetimeTimer|.
735751

736752
1. Let |issuedRequests| be a new [=ordered set=].
@@ -778,6 +794,12 @@ When this method is invoked, the user agent MUST execute the following algorithm
778794
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
779795
and [=set/remove=] |authenticator| from |issuedRequests|.
780796

797+
: If the <code>|options|.{{CredentialCreationOptions/signal}}</code> is [=present=] and its
798+
[=AbortSignal/aborted flag=] is set to true,
799+
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=]
800+
operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. Then return a {{DOMException}}
801+
whose name is "{{AbortError}}" and terminate this algorithm.
802+
781803
: If any |authenticator| returns a status indicating that the user cancelled the operation,
782804
:: 1. [=set/Remove=] |authenticator| from |issuedRequests|.
783805
2. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on
@@ -949,6 +971,10 @@ method is invoked, the user agent MUST:
949971

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

974+
1. If the <code>|options|.{{CredentialRequestOptions/signal}}</code> is [=present=] and its
975+
[=AbortSignal/aborted flag=] is set to true, return a {{DOMException}} whose name is "{{AbortError}}"
976+
and terminate this algorithm.
977+
952978
1. Let |issuedRequests| be a new [=ordered set=].
953979

954980
1. Let |authenticator| be a platform-specific handle whose value identifies an [=authenticator=].
@@ -1028,6 +1054,12 @@ method is invoked, the user agent MUST:
10281054
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on
10291055
|authenticator| and [=set/remove=] |authenticator| from |issuedRequests|.
10301056

1057+
: If the {{CredentialRequestOptions/signal}} member is [=present=] and the [=AbortSignal/aborted flag=] is set to
1058+
true,
1059+
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
1060+
and [=set/remove=] |authenticator| from |issuedRequests|. Then
1061+
return a {{DOMException}} whose name is "{{AbortError}}" and terminate this algorithm.
1062+
10311063
: If any |authenticator| returns a status indicating that the user cancelled the operation,
10321064
:: 1. [=set/Remove=] |authenticator| from |issuedRequests|.
10331065
2. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation
@@ -1132,7 +1164,6 @@ but short enough that the dangling promise will still be resolved in a reasonabl
11321164

11331165
</div>
11341166

1135-
11361167
## Authenticator Responses (interface <dfn interface>AuthenticatorResponse</dfn>) ## {#iface-authenticatorresponse}
11371168

11381169
[=Authenticators=] respond to [=[RP]=] requests by returning an object derived from the
@@ -1467,14 +1498,41 @@ an assertion. Its {{PublicKeyCredentialRequestOptions/challenge}} member must be
14671498
:: This optional member contains a list of {{PublicKeyCredentialDescriptor}} object representing [=public key credentials=]
14681499
acceptable to the caller, in decending order of the caller's preference (the first item in the list is the most
14691500
preferred credential, and so on down the list).
1470-
1501+
14711502
: <dfn>extensions</dfn>
14721503
:: This optional member contains additional parameters requesting additional processing by the client and authenticator.
14731504
For example, if transaction confirmation is sought from the user, then the prompt string might be included as an
14741505
extension.
14751506
</dl>
14761507

14771508

1509+
## Abort operations with `AbortSignal` ## {#abortoperation}
1510+
1511+
Developers are encouraged to leverage the {{AbortController}} to manage the
1512+
{{PublicKeyCredential/[[Create]](options)}} and {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}} operations.
1513+
See [[dom#abortcontroller-api-integration]] section for detailed instructions.
1514+
1515+
Note: [[dom#abortcontroller-api-integration]] section specifies that web platform APIs integrating with the
1516+
{{AbortController}} must reject the promise immediately once the [=AbortSignal/aborted flag=] is set.
1517+
Given the complex inheritance and parallelization structure of the {{PublicKeyCredential/[[Create]](options)}}
1518+
and {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}} methods, the algorithms for the two APIs fulfills this
1519+
requirement by checking the [=AbortSignal/aborted flag=] in three places. In the case of
1520+
{{PublicKeyCredential/[[Create]](options)}}, the aborted flag is checked first in
1521+
[[credential-management-1#algorithm-create]] right before calling {{Credential/[[Create]](options)}},
1522+
then in [[#createCredential]] right before authenticator sessions start, and finally
1523+
during authenticator sessions. The same goes for
1524+
{{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}}.
1525+
1526+
The [=visibility states|visibility=] and [=focus=] state of the [=Window=] object determines whether the
1527+
{{PublicKeyCredential/[[Create]](options)}} and {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}} operations
1528+
should continue. When the [=Window=] object associated with the [[=Document=] loses focus,
1529+
{{PublicKeyCredential/[[Create]](options)}} and {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}} operations
1530+
SHOULD be aborted.
1531+
1532+
Issue: The WHATWG HTML WG is discussing whether to provide a hook when a browsing context gains or
1533+
loses focuses. If a hook is provided, the above paragraph will be updated to include the hook.
1534+
See [WHATWG HTML WG Issue #2711](https://github.com/whatwg/html/issues/2711) for more details.
1535+
14781536
## Authentication Extensions (typedef <dfn>AuthenticationExtensions</dfn>) ## {#iface-authentication-extensions}
14791537

14801538
<pre class="idl">
@@ -3808,6 +3866,42 @@ extension for transaction authorization.
38083866
});
38093867
</pre>
38103868

3869+
## Aborting Authentication Operations ## {#sample-aborting}
3870+
3871+
The below example shows how a developer may use the AbortSignal parameter to abort a
3872+
credential registration operation. A similiar procedure applies to an authentication operation.
3873+
3874+
<pre class="example" highlight="js">
3875+
const authAbortController = new AbortController();
3876+
const authAbortSignal = authAbortController.signal;
3877+
3878+
authAbortSignal.onabort = function () {
3879+
// Once the page knows the abort started, inform user it is attempting to abort.
3880+
}
3881+
3882+
var options = {
3883+
// A list of options.
3884+
}
3885+
3886+
navigator.credentials.create({
3887+
publicKey: options,
3888+
signal: authAbortSignal})
3889+
.then(function (attestation) {
3890+
// Register the user.
3891+
}).catch(function (error) {
3892+
if (error == "AbortError") {
3893+
// Inform user the credential hasn't been created.
3894+
// Let the server know a key hasn't been created.
3895+
}
3896+
});
3897+
3898+
// Assume widget shows up whenever auth occurs.
3899+
if (widget == "disappear") {
3900+
authAbortSignal.abort();
3901+
3902+
}
3903+
</pre>
3904+
38113905

38123906
## Decommissioning ## {#sample-decommissioning}
38133907

0 commit comments

Comments
 (0)