diff --git a/index.bs b/index.bs index f1395a821..e34545481 100644 --- a/index.bs +++ b/index.bs @@ -91,10 +91,20 @@ spec: credential-management-1; urlPrefix: https://w3c.github.io/webappsec-creden for: CredentialsContainer type: method text: create(); url: dom-credentialscontainer-create + type: dfn + text: signal spec: mixed-content; urlPrefix: www.w3.org/TR/mixed-content/ type: dfn text: a priori authenticated + +spec: page-visibility; urlPrefix: https://www.w3.org/TR/page-visibility/ + type: dfn + text: visibility states + +spec: WHATWG HTML; urlPrefix: https://html.spec.whatwg.org/ + type: dfn + text: focus
@@ -570,7 +580,9 @@ To support obtaining assertions via {{CredentialsContainer/get()|navigator.crede {{CredentialsContainer/create()|navigator.credentials.create()}} to request the creation of a new [=credential key pair=] and {{PublicKeyCredential}}, managed by an [=authenticator=]. On success, the returned {{promise}} will be resolved with a {{PublicKeyCredential}} containing an -{{AuthenticatorAttestationResponse}} object. +{{AuthenticatorAttestationResponse}} object. This {{CredentialsContainer/create()|navigator.credentials.create()}} +operation can be aborted by leveraging the {{AbortController}}; see +[[dom#abortcontroller-api-integration]] for detailed instructions. Note: This algorithm is synchronous; the {{Promise}} resolution/rejection is handled by {{CredentialsContainer/create()|navigator.credentials.create()}}. @@ -688,6 +700,10 @@ 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|options|.{{CredentialCreationOptions/signal}}
is [=present=] and its + [=AbortSignal/aborted flag=] is set to true, return a {{DOMException}} whose name is "{{AbortError}}" + and terminate this algorithm. + 1. Start |lifetimeTimer|. 1. Let |issuedRequests| be a new [=ordered set=]. @@ -735,6 +751,12 @@ When this method is invoked, the user agent MUST execute the following algorithm :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. + : If the|options|.{{CredentialCreationOptions/signal}}
is [=present=] and its + [=AbortSignal/aborted flag=] is set to true, + :: [=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. + : If any |authenticator| returns a status indicating that the user cancelled the operation, :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. 2. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on @@ -906,6 +928,10 @@ method is invoked, the user agent MUST: 1. Let |clientDataHash| be the [=hash of the serialized client data=] represented by |clientDataJSON|. +1. If the|options|.{{CredentialRequestOptions/signal}}
is [=present=] and its + [=AbortSignal/aborted flag=] is set to true, return a {{DOMException}} whose name is "{{AbortError}}" + and terminate this algorithm. + 1. Let |issuedRequests| be a new [=ordered set=]. 1. Let |authenticator| be a platform-specific handle whose value identifies an [=authenticator=]. @@ -985,6 +1011,12 @@ method is invoked, the user agent MUST: :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. + : If the {{CredentialRequestOptions/signal}} member is [=present=] and the [=AbortSignal/aborted flag=] is set to + true, + :: [=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. + : If any |authenticator| returns a status indicating that the user cancelled the operation, :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. 2. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation @@ -1089,7 +1121,6 @@ but short enough that the dangling promise will still be resolved in a reasonabl - ## Authenticator Responses (interface AuthenticatorResponse) ## {#iface-authenticatorresponse} [=Authenticators=] respond to [=[RP]=] requests by returning an object derived from the @@ -1418,7 +1449,7 @@ an assertion. Its {{PublicKeyCredentialRequestOptions/challenge}} member must be :: This optional member contains a list of {{PublicKeyCredentialDescriptor}} object representing [=public key credentials=] acceptable to the caller, in decending order of the caller's preference (the first item in the list is the most preferred credential, and so on down the list). - + : extensions :: This optional member contains additional parameters requesting additional processing by the client and authenticator. For example, if transaction confirmation is sought from the user, then the prompt string might be included as an @@ -1426,6 +1457,33 @@ an assertion. Its {{PublicKeyCredentialRequestOptions/challenge}} member must be +## Abort operations with `AbortSignal` ## {#abortoperation} + +Developers are encouraged to leverage the {{AbortController}} to manage the +{{PublicKeyCredential/[[Create]](options)}} and {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}} operations. +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. + Given the complex inheritance and parallelization structure of the {{PublicKeyCredential/[[Create]](options)}} + and {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}} 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]](options)}}, the aborted flag is checked first in + [[credential-management-1#algorithm-create]] right before calling {{Credential/[[Create]](options)}}, + then in [[#createCredential]] right before authenticator sessions start, and finally + during authenticator sessions. The same goes for + {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}}. + +The [=visibility states|visibility=] and [=focus=] state of the [=Window=] object determines whether the +{{PublicKeyCredential/[[Create]](options)}} and {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}} operations +should continue. When the [=Window=] object associated with the [[=Document=] loses focus, +{{PublicKeyCredential/[[Create]](options)}} and {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}} operations +SHOULD be aborted. + + Issue: The WHATWG HTML WG is discussing whether to provide a hook when a browsing context gains or + loses focuses. If a hook is provided, the above paragraph will be updated to include the hook. + See [WHATWG HTML WG Issue #2711](https://github.com/whatwg/html/issues/2711) for more details. + ## Authentication Extensions (typedef AuthenticationExtensions) ## {#iface-authentication-extensions}@@ -3754,6 +3812,42 @@ extension for transaction authorization. });+## Aborting Authentication Operations ## {#sample-aborting} + +The below example shows how a developer may use the AbortSignal parameter to abort a +credential registration operation. A similiar procedure applies to an authentication operation. + ++ const authAbortController = new AbortController(); + const authAbortSignal = authAbortController.signal; + + authAbortSignal.onabort = function () { + // Once the page knows the abort started, inform user it is attempting to abort. + } + + var options = { + // A list of options. + } + + navigator.credentials.create({ + publicKey: options, + signal: authAbortSignal}) + .then(function (attestation) { + // Register the user. + }).catch(function (error) { + if (error == "AbortError") { + // Inform user the credential hasn't been created. + // Let the server know a key hasn't been created. + } + }); + + // Assume widget shows up whenever auth occurs. + if (widget == "disappear") { + authAbortSignal.abort(); + + } ++ ## Decommissioning ## {#sample-decommissioning}