From ed25b6c10864378b6843f1b1d167afa3628865de Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 16 Jun 2017 14:43:46 -0700 Subject: [PATCH 01/37] do not call authenticatorMakeCredential() with separate |rpId| fixes #466 --- index.bs | 56 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/index.bs b/index.bs index bd6d1ec20..4e48edc50 100644 --- a/index.bs +++ b/index.bs @@ -526,11 +526,12 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Let |options| be the value of |options|.{{CredentialCreationOptions/publicKey}}. -1. If any of the {{PublicKeyCredentialEntity/name}} member of |options|.{{MakeCredentialOptions/rp}}, the - {{PublicKeyCredentialEntity/name}} member of |options|.{{MakeCredentialOptions/user}}, +1. If any of the {{PublicKeyCredentialEntity/name}} member of |options|.{{MakeCredentialOptions/rp}}, the + {{PublicKeyCredentialEntity/name}} member of |options|.{{MakeCredentialOptions/user}}, the {{PublicKeyCredentialUserEntity/displayName}} member of |options|.{{MakeCredentialOptions/user}}, or the {{PublicKeyCredentialEntity/id}} - member of |options|.{{MakeCredentialOptions/user}} are [=present|not present=], return a {{TypeError}} [=simple exception=]. + member of |options|.{{MakeCredentialOptions/user}} are [=present|not present=], return a {{TypeError}} + [=simple exception=]. 1. If the {{MakeCredentialOptions/timeout}} member of |options| is [=present=], check if its value lies within a reasonable range as defined by the platform and if not, correct it to the closest value lying within that range. Set @@ -551,29 +552,34 @@ When this method is invoked, the user agent MUST execute the following algorithm [=ipv6 address=], [=opaque host=], or [=empty host=] -- are disallowed. --> -1. Let |rpId| be |effectiveDomain|. -
  • - If |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} is [=present=]: + If |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} +
    + + : Is [=present=] + :: If |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} [=is not a + registrable domain suffix of and is not equal to=] |effectiveDomain|, return a {{DOMException}} whose name + is "{{SecurityError}}", and terminate this algorithm. - 1. If |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} [=is not a registrable domain suffix of - and is not equal to=] |effectiveDomain|, return a {{DOMException}} whose name is "{{SecurityError}}", and terminate - this algorithm. + : Is [=present|not present=] + :: Set |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} to + |effectiveDomain|. - 1. Set |rpId| to |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}}. +
    - Note: |rpId| represents the caller's [=RP ID=]. The [=RP ID=] defaults to being the caller's [=environment settings - object/origin=]'s [=effective domain=] unless the caller has explicitly set - |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} when calling + Note: |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} represents the caller's + [=RP ID=]. The [=RP ID=] defaults to being the caller's [=environment settings object/origin=]'s [=effective + domain=] unless the caller has explicitly set + |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} when calling {{CredentialsContainer/create()}}.
  • 1. Let |normalizedParameters| be a new [=list=] whose [=list/items=] are pairs of {{PublicKeyCredentialType}} and a [=dictionary=] type (as returned by [=normalizing an algorithm=]). -1. [=list/For each=] |current| of |options|.{{MakeCredentialOptions/parameters}}: +1. [=list/For each=] |current| of |options|.{{MakeCredentialOptions/parameters}}: 1. If |current|.{{PublicKeyCredentialParameters/type}} does not contain a {{PublicKeyCredentialType}} supported by this implementation, then [=continue=]. 1. Let |normalizedAlgorithm| be the result of [=normalizing an algorithm=] [[!WebCryptoAPI]], with |alg| set to @@ -582,9 +588,9 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. [=list/Append=] the pair of |current|.{{PublicKeyCredentialParameters/type}} and |normalizedAlgorithm| to |normalizedParameters|. -1. If |normalizedParameters| [=list/is empty=] and |options|.{{MakeCredentialOptions/parameters}} [=list/is not empty=], - cancel the timer started in step 2, return a {{DOMException}} whose name is "{{NotSupportedError}}", and terminate this - algorithm. +1. If |normalizedParameters| [=list/is empty=] and |options|.{{MakeCredentialOptions/parameters}} + [=list/is not empty=], cancel the timer started in step 2, return a {{DOMException}} whose name is "{{NotSupportedError}}", + and terminate this algorithm. 1. Let |clientExtensions| be a new [=map=] and let |authenticatorExtensions| be a new [=map=]. @@ -628,7 +634,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. If |currentlyAvailableAuthenticators| [=list/is empty=], return a {{DOMException}} whose name is "{{NotFoundError}}", and terminate this algorithm. -1. If |options|.{{MakeCredentialOptions/authenticatorSelection}} is [=present|present=], iterate through +1. If |options|.{{MakeCredentialOptions/authenticatorSelection}} is [=present|present=], iterate through |currentlyAvailableAuthenticators| and do the following [=set/for each=] |authenticator|: 1. If {{AuthenticatorSelectionCriteria/attachment}} is [=present|present=] and its value is not equal to |authenticator|'s attachment modality, [=iteration/continue=]. @@ -647,8 +653,8 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. If |C|.{{transports}} [=list/is not empty=], and |authenticator| is connected over a transport not mentioned in |C|.{{transports}}, the client MAY [=continue=]. 1. Otherwise, [=list/Append=] |C| to |excludeCredentialDescriptorList|. - 1. [=In parallel=], invoke the [=authenticatorMakeCredential=] operation on |authenticator| with |rpId|, - |clientDataHash|, |options|.{{MakeCredentialOptions/rp}}, |options|.{{MakeCredentialOptions/user}}, + 1. [=In parallel=], invoke the [=authenticatorMakeCredential=] operation on |authenticator| with + |clientDataHash|, |options|.{{MakeCredentialOptions/rp}}, |options|.{{MakeCredentialOptions/user}}, |normalizedParameters|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. 1. [=set/Append=] |authenticator| to |issuedRequests|. @@ -693,7 +699,7 @@ When this method is invoked, the user agent MUST execute the following algorithm : {{PublicKeyCredential/clientExtensionResults}} :: A new {{AuthenticationExtensions}} object containing the [=extension identifier=] → [=client extension output=] entries created by running each extension's [=client extension processing=] algorithm to create the [=client - extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. + extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. 5. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] it from |issuedRequests|. @@ -761,7 +767,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 + 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. @@ -825,7 +831,7 @@ When this method is invoked, the user agent MUST execute the following algorithm |options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}.{{PublicKeyCredentialDescriptor/type}}. Set |allowCredentialDescriptorList| to this filtered list. - 1. If |allowCredentialDescriptorList| + 1. If |allowCredentialDescriptorList|
    : [=list/is not empty=] :: 1. Let |distinctTransports| be a new [=ordered set=]. @@ -1537,9 +1543,9 @@ The following operations can be invoked by the client in an authenticator sessio This operation must be invoked in an authenticator session which has no other operations in progress. It takes the following input parameters: -- The caller's [=RP ID=], as determined by the user agent and the client. - The [=hash of the serialized client data=], provided by the client. -- The [=[RP]=]'s {{PublicKeyCredentialEntity}}. +- The [=[RP]=]'s {{PublicKeyCredentialEntity}}. This contains the caller's [=RP ID=], as + determined by the user agent and the client. - The user account's {{PublicKeyCredentialUserEntity}}. - A sequence of pairs of {{PublicKeyCredentialType}} and cryptographic algorithms (a dictionary type) requested by the [=[RP]=], where the cryptographic algorithms are normalized as per the procedure in From 31a8f855649dd120141d7ed42290d39e8c1d897e Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 16 Jun 2017 16:10:48 -0700 Subject: [PATCH 02/37] credID returned by authnrGetAssn() is optional if allowCreds has exactly 1 member fixes #472 --- index.bs | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/index.bs b/index.bs index 4e48edc50..f68374f11 100644 --- a/index.bs +++ b/index.bs @@ -836,6 +836,10 @@ When this method is invoked, the user agent MUST execute the following algorithm : [=list/is not empty=] :: 1. Let |distinctTransports| be a new [=ordered set=]. + 1. If |allowCredentialDescriptorList| has exactly one value, let |savedCredentialId| be a new {{ArrayBuffer}}, + created using |global|'s [=%ArrayBuffer%=], and containing the bytes of + |allowCredentialDescriptorList|[0].id. + 1. [=list/For each=] credential descriptor |C| in |allowCredentialDescriptorList|, [=set/append=] each value, if any, of |C|.{{transports}} to |distinctTransports|. @@ -879,28 +883,29 @@ When this method is invoked, the user agent MUST execute the following algorithm
    -
    If the |adjustedTimeout| timer expires,
    -
    [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| - and [=set/remove=] |authenticator| from |issuedRequests|.
    + : If the |adjustedTimeout| timer expires, + :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| + and [=set/remove=] |authenticator| from |issuedRequests|. -
    If any |authenticator| returns a status indicating that the user cancelled the operation,
    -
    - 1. [=set/Remove=] |authenticator| from |issuedRequests|. + : 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 |authenticator| and [=set/remove=] it from |issuedRequests|. -
    -
    If any |authenticator| returns an error status,
    -
    [=set/Remove=] |authenticator| from |issuedRequests|.
    -
    If any |authenticator| indicates success,
    -
    - 1. [=set/Remove=] |authenticator| from |issuedRequests|. + : If any |authenticator| returns an error status, + :: [=set/Remove=] |authenticator| from |issuedRequests|. + + : If any |authenticator| indicates success, + :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. 2. Let |value| be a new {{PublicKeyCredential}} associated with |global| whose fields are: : {{PublicKeyCredential/[[identifier]]}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the credential ID - returned from the successful [=authenticatorGetAssertion=] operation, as defined in [[#op-get-assertion]]. + :: Create a new {{ArrayBuffer}}, using |global|'s [=%ArrayBuffer%=]. + If |savedCredentialId| exists, set the value of the new {{ArrayBuffer}} to be the bytes of + |savedCredentialId|. Otherwise, set the value of the new {{ArrayBuffer}} to be the bytes of the credential + ID returned from the successful [=authenticatorGetAssertion=] operation, as defined in + [[#op-get-assertion]]. : {{PublicKeyCredential/response}} :: A new {{AuthenticatorAssertionResponse}} object associated with |global| whose fields are: : {{AuthenticatorResponse/clientDataJSON}} @@ -919,7 +924,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 3. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] it from |issuedRequests|. 4. Return |value| and terminate this algorithm. -
    +
    1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". @@ -1623,7 +1628,12 @@ When this method is invoked, the [=authenticator=] must perform the following pr On successful completion, the authenticator returns to the user agent: -- The identifier of the credential (credential ID) used to generate the [=assertion signature=]. +- The identifier of the credential (credential ID) used to generate the [=assertion signature=], if either a list of + credentials of length 2 or greater was supplied by the client, or no such list was supplied. + + Note: If the client supplies a list of exactly one credential and it was successfully employed, then its credential ID + is not returned since the client already knows it. + - The [=authenticator data=] used to generate the [=assertion signature=]. - The [=assertion signature=]. From 9c3940fbc89d304f3fddd175f0262f8ff9b5a2db Mon Sep 17 00:00:00 2001 From: JeffH Date: Tue, 20 Jun 2017 16:10:09 -0700 Subject: [PATCH 03/37] fixup global object reference per domenic, improves #472 --- index.bs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.bs b/index.bs index f68374f11..90525fef8 100644 --- a/index.bs +++ b/index.bs @@ -747,8 +747,7 @@ When this method is invoked, the user agent MUST execute the following algorithm Set |adjustedTimeout| to this adjusted value. If the {{PublicKeyCredentialRequestOptions/timeout}} member of |options| is [=present|not present=], then set |adjustedTimeout| to a platform-specific default. -1. Let |global| be the {{PublicKeyCredential}}'s [=interface object=]'s [=global object|environment settings object's global - object=]. +1. Let |global| be the {{PublicKeyCredential}}'s [=interface object=]'s [=relevant global object=]. 1. Let |callerOrigin| be the [=environment settings object/origin=] specified by this {{PublicKeyCredential}} [=interface object=]'s [=relevant settings object=]. If |callerOrigin| is an [=opaque origin=], return a {{DOMException}} whose name is From be436658c7c49f446b0ad8876ca841d8d3bf40be Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 28 Jun 2017 15:41:29 -0700 Subject: [PATCH 04/37] indent 4.1.4 step 18et al to clarify relation to prior step --- index.bs | 92 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/index.bs b/index.bs index 90525fef8..dfbde9daa 100644 --- a/index.bs +++ b/index.bs @@ -877,54 +877,56 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Start a timer for |adjustedTimeout| milliseconds. Then execute the following steps [=in parallel=]. The [=task source=] for these [=tasks=] is the [=dom manipulation task source=]. -1. While |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer and - responses from the authenticators: - -
    - - : If the |adjustedTimeout| timer expires, - :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| - and [=set/remove=] |authenticator| from |issuedRequests|. - - : 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 - |authenticator| and [=set/remove=] it from |issuedRequests|. - - - : If any |authenticator| returns an error status, - :: [=set/Remove=] |authenticator| from |issuedRequests|. + 1. While |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer + and responses from the authenticators: - : If any |authenticator| indicates success, - :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. - 2. Let |value| be a new {{PublicKeyCredential}} associated with |global| whose fields are: - - : {{PublicKeyCredential/[[identifier]]}} - :: Create a new {{ArrayBuffer}}, using |global|'s [=%ArrayBuffer%=]. - If |savedCredentialId| exists, set the value of the new {{ArrayBuffer}} to be the bytes of - |savedCredentialId|. Otherwise, set the value of the new {{ArrayBuffer}} to be the bytes of the credential - ID returned from the successful [=authenticatorGetAssertion=] operation, as defined in - [[#op-get-assertion]]. - : {{PublicKeyCredential/response}} - :: A new {{AuthenticatorAssertionResponse}} object associated with |global| whose fields are: - : {{AuthenticatorResponse/clientDataJSON}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of |clientDataJSON| - : {{AuthenticatorAssertionResponse/authenticatorData}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned - {{authenticatorData}} - : {{AuthenticatorAssertionResponse/signature}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned - {{signature}} - : {{PublicKeyCredential/clientExtensionResults}} - :: A new {{AuthenticationExtensions}} object containing the [=extension identifier=] → [=client extension output=] - entries created by running each extension's [=client extension processing=] algorithm to create the [=client - extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. +
    - 3. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on - |authenticator| and [=set/remove=] it from |issuedRequests|. - 4. Return |value| and terminate this algorithm. + : If the |adjustedTimeout| timer expires, + :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| + and [=set/remove=] |authenticator| from |issuedRequests|. + + : 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 + |authenticator| and [=set/remove=] it from |issuedRequests|. + + + : If any |authenticator| returns an error status, + :: [=set/Remove=] |authenticator| from |issuedRequests|. + + : If any |authenticator| indicates success, + :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. + 2. Let |value| be a new {{PublicKeyCredential}} associated with |global| whose fields are: + + : {{PublicKeyCredential/[[identifier]]}} + :: Create a new {{ArrayBuffer}}, using |global|'s [=%ArrayBuffer%=]. + If |savedCredentialId| exists, set the value of the new {{ArrayBuffer}} to be the bytes of + |savedCredentialId|. Otherwise, set the value of the new {{ArrayBuffer}} to be the bytes of the + credential ID returned from the successful [=authenticatorGetAssertion=] operation, as defined in + [[#op-get-assertion]]. + : {{PublicKeyCredential/response}} + :: A new {{AuthenticatorAssertionResponse}} object associated with |global| whose fields are: + : {{AuthenticatorResponse/clientDataJSON}} + :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of + |clientDataJSON| + : {{AuthenticatorAssertionResponse/authenticatorData}} + :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned + {{authenticatorData}} + : {{AuthenticatorAssertionResponse/signature}} + :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned + {{signature}} + : {{PublicKeyCredential/clientExtensionResults}} + :: A new {{AuthenticationExtensions}} object containing the [=extension identifier=] → [=client extension + output=] entries created by running each extension's [=client extension processing=] algorithm to create the + [=client extension outputs=], for each [=client extension=] in + {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. + + 3. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on + |authenticator| and [=set/remove=] it from |issuedRequests|. + 4. Return |value| and terminate this algorithm. -
    +
    1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". From 9ce433172d3fd0a2bac90bdff514cb377889bc56 Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 28 Jun 2017 15:42:33 -0700 Subject: [PATCH 05/37] fix line indent --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index dfbde9daa..afaf939dd 100644 --- a/index.bs +++ b/index.bs @@ -909,7 +909,7 @@ When this method is invoked, the user agent MUST execute the following algorithm :: A new {{AuthenticatorAssertionResponse}} object associated with |global| whose fields are: : {{AuthenticatorResponse/clientDataJSON}} :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of - |clientDataJSON| + |clientDataJSON| : {{AuthenticatorAssertionResponse/authenticatorData}} :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned {{authenticatorData}} From 5f543b88bea0f8c3e301be6e9814551f140205f8 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 16 Jun 2017 14:43:46 -0700 Subject: [PATCH 06/37] do not call authenticatorMakeCredential() with separate |rpId| fixes #466 --- index.bs | 54 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/index.bs b/index.bs index 725db36ea..d9c123d5d 100644 --- a/index.bs +++ b/index.bs @@ -558,11 +558,11 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Let |options| be the value of |options|.{{CredentialCreationOptions/publicKey}}. -1. If any of the {{PublicKeyCredentialEntity/name}} member of |options|.{{MakePublicKeyCredentialOptions/rp}}, the - {{PublicKeyCredentialEntity/name}} member of |options|.{{MakePublicKeyCredentialOptions/user}}, - the {{PublicKeyCredentialUserEntity/displayName}} member of |options|.{{MakePublicKeyCredentialOptions/user}}, +1. If any of the {{PublicKeyCredentialEntity/name}} member of |options|.{{MakePublicKeyCredentialOptions/rp}}, the + {{PublicKeyCredentialEntity/name}} member of |options|.{{MakePublicKeyCredentialOptions/user}}, + the {{PublicKeyCredentialUserEntity/displayName}} member of |options|.{{MakePublicKeyCredentialOptions/user}}, or the {{PublicKeyCredentialEntity/id}} - member of |options|.{{MakePublicKeyCredentialOptions/user}} are [=present|not present=], return a {{TypeError}} [=simple exception=]. + member of |options|.{{MakePublicKeyCredentialOptions/user}} are [=present|not present=], return a {{TypeError}} [=simple exception=]. 1. If the {{MakePublicKeyCredentialOptions/timeout}} member of |options| is [=present=], check if its value lies within a reasonable range as defined by the platform and if not, correct it to the closest value lying within that range. Set @@ -584,36 +584,41 @@ When this method is invoked, the user agent MUST execute the following algorithm such as [=domain=], [=ipv4 address=], [=ipv6 address=], [=opaque host=], or [=empty host=]. Only the [=domain=] format of [=host=] is allowed here. -1. Let |rpId| be |effectiveDomain|. -
  • - If |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} is [=present=]: + If |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} +
    + + : Is [=present=] + :: If |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} [=is not a + registrable domain suffix of and is not equal to=] |effectiveDomain|, return a {{DOMException}} whose name + is "{{SecurityError}}", and terminate this algorithm. - 1. If |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} [=is not a registrable domain suffix of - and is not equal to=] |effectiveDomain|, return a {{DOMException}} whose name is "{{SecurityError}}", and terminate - this algorithm. + : Is [=present|not present=] + :: Set |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} to + |effectiveDomain|. - 1. Set |rpId| to |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}}. +
    - Note: |rpId| represents the caller's [=RP ID=]. The [=RP ID=] defaults to being the caller's [=environment settings - object/origin=]'s [=effective domain=] unless the caller has explicitly set - |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} when calling + Note: |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} represents the caller's + [=RP ID=]. The [=RP ID=] defaults to being the caller's [=environment settings object/origin=]'s [=effective + domain=] unless the caller has explicitly set + |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} when calling {{CredentialsContainer/create()}}.
  • 1. Let |credTypesAndPubKeyAlgs| be a new [=list=] whose [=list/items=] are pairs of {{PublicKeyCredentialType}} and a {{COSEAlgorithmIdentifier}}. -1. [=list/For each=] |current| of |options|.{{MakePublicKeyCredentialOptions/pubKeyCredParams}}: +1. [=list/For each=] |current| of |options|.{{MakePublicKeyCredentialOptions/parameters}}: 1. If |current|.{{PublicKeyCredentialParameters/type}} does not contain a {{PublicKeyCredentialType}} supported by this implementation, then [=continue=]. 1. Let |alg| be |current|.{{PublicKeyCredentialParameters/alg}}. 1. [=list/Append=] the pair of |current|.{{PublicKeyCredentialParameters/type}} and |alg| to |credTypesAndPubKeyAlgs|. -1. If |credTypesAndPubKeyAlgs| [=list/is empty=] and |options|.{{MakePublicKeyCredentialOptions/pubKeyCredParams}} +1. If |normalizedParameters| [=list/is empty=] and |options|.{{MakePublicKeyCredentialOptions/parameters}} [=list/is not empty=], cancel the timer started in step 2, return a {{DOMException}} whose name is "{{NotSupportedError}}", and terminate this algorithm. @@ -659,7 +664,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. If |currentlyAvailableAuthenticators| [=list/is empty=], return a {{DOMException}} whose name is "{{NotFoundError}}", and terminate this algorithm. -1. If |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}} is [=present|present=], iterate through +1. If |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}} is [=present|present=], iterate through |currentlyAvailableAuthenticators| and do the following [=set/for each=] |authenticator|: 1. If {{AuthenticatorSelectionCriteria/aa}} is [=present|present=] and its value is not equal to |authenticator|'s attachment modality, [=iteration/continue=]. @@ -680,10 +685,11 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. If |C|.{{transports}} [=list/is not empty=], and |authenticator| is connected over a transport not mentioned in |C|.{{transports}}, the client MAY [=continue=]. 1. Otherwise, [=list/Append=] |C| to |excludeCredentialDescriptorList|. - 1. [=In parallel=], invoke the [=authenticatorMakeCredential=] operation on |authenticator| with |rpId|, - |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, - |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/rk}}, - |credTypesAndPubKeyAlgs|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. + + 1. [=In parallel=], invoke the [=authenticatorMakeCredential=] operation on |authenticator| with + |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakeCredentialOptions/user}}, + |normalizedParameters|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. + 1. [=set/Append=] |authenticator| to |issuedRequests|. 1. Start a timer for |adjustedTimeout| milliseconds. Then execute the following steps [=in parallel=]. The [=task source=] for @@ -727,7 +733,7 @@ When this method is invoked, the user agent MUST execute the following algorithm : {{PublicKeyCredential/clientExtensionResults}} :: A new {{AuthenticationExtensions}} object containing the [=extension identifier=] → [=client extension output=] entries created by running each extension's [=client extension processing=] algorithm to create the [=client - extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. + extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. 5. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] it from |issuedRequests|. @@ -1636,9 +1642,9 @@ The following operations can be invoked by the client in an authenticator sessio This operation must be invoked in an authenticator session which has no other operations in progress. It takes the following input parameters: -- The caller's [=RP ID=], as determined by the user agent and the client. - The [=hash of the serialized client data=], provided by the client. -- The [=[RP]=]'s {{PublicKeyCredentialEntity}}. +- The [=[RP]=]'s {{PublicKeyCredentialEntity}}. This contains the caller's [=RP ID=], as + determined by the user agent and the client. - The user account's {{PublicKeyCredentialUserEntity}}. - A sequence of pairs of {{PublicKeyCredentialType}} and {{COSEAlgorithmIdentifier}} requested by the [=[RP]=]. This sequence is ordered from most preferred to least From d8fd53bbb338967f243063f2d9848746df5e5a23 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 16 Jun 2017 16:10:48 -0700 Subject: [PATCH 07/37] credID returned by authnrGetAssn() is optional if allowCreds has exactly 1 member fixes #472 --- index.bs | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/index.bs b/index.bs index d9c123d5d..cd006b61b 100644 --- a/index.bs +++ b/index.bs @@ -871,6 +871,10 @@ When this method is invoked, the user agent MUST execute the following algorithm : [=list/is not empty=] :: 1. Let |distinctTransports| be a new [=ordered set=]. + 1. If |allowCredentialDescriptorList| has exactly one value, let |savedCredentialId| be a new {{ArrayBuffer}}, + created using |global|'s [=%ArrayBuffer%=], and containing the bytes of + |allowCredentialDescriptorList|[0].id. + 1. [=list/For each=] credential descriptor |C| in |allowCredentialDescriptorList|, [=set/append=] each value, if any, of |C|.{{transports}} to |distinctTransports|. @@ -915,28 +919,29 @@ When this method is invoked, the user agent MUST execute the following algorithm
    -
    If the |adjustedTimeout| timer expires,
    -
    [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| - and [=set/remove=] |authenticator| from |issuedRequests|.
    + : If the |adjustedTimeout| timer expires, + :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| + and [=set/remove=] |authenticator| from |issuedRequests|. -
    If any |authenticator| returns a status indicating that the user cancelled the operation,
    -
    - 1. [=set/Remove=] |authenticator| from |issuedRequests|. + : 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 |authenticator| and [=set/remove=] it from |issuedRequests|. -
    -
    If any |authenticator| returns an error status,
    -
    [=set/Remove=] |authenticator| from |issuedRequests|.
    -
    If any |authenticator| indicates success,
    -
    - 1. [=set/Remove=] |authenticator| from |issuedRequests|. + : If any |authenticator| returns an error status, + :: [=set/Remove=] |authenticator| from |issuedRequests|. + + : If any |authenticator| indicates success, + :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. 2. Let |value| be a new {{PublicKeyCredential}} associated with |global| whose fields are: : {{PublicKeyCredential/[[identifier]]}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the credential ID - returned from the successful [=authenticatorGetAssertion=] operation, as defined in [[#op-get-assertion]]. + :: Create a new {{ArrayBuffer}}, using |global|'s [=%ArrayBuffer%=]. + If |savedCredentialId| exists, set the value of the new {{ArrayBuffer}} to be the bytes of + |savedCredentialId|. Otherwise, set the value of the new {{ArrayBuffer}} to be the bytes of the credential + ID returned from the successful [=authenticatorGetAssertion=] operation, as defined in + [[#op-get-assertion]]. : {{PublicKeyCredential/response}} :: A new {{AuthenticatorAssertionResponse}} object associated with |global| whose fields are: : {{AuthenticatorResponse/clientDataJSON}} @@ -954,6 +959,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 3. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] it from |issuedRequests|. + 4. Return |value| and terminate this algorithm.
    @@ -1724,7 +1730,12 @@ When this method is invoked, the [=authenticator=] must perform the following pr On successful completion, the authenticator returns to the user agent: -- The identifier of the credential (credential ID) used to generate the [=assertion signature=]. +- The identifier of the credential (credential ID) used to generate the [=assertion signature=], if either a list of + credentials of length 2 or greater was supplied by the client, or no such list was supplied. + + Note: If the client supplies a list of exactly one credential and it was successfully employed, then its credential ID + is not returned since the client already knows it. + - The [=authenticator data=] used to generate the [=assertion signature=]. - The [=assertion signature=]. From c9b40d5c30011eb0b981a9434942a462482a2e56 Mon Sep 17 00:00:00 2001 From: JeffH Date: Tue, 20 Jun 2017 16:10:09 -0700 Subject: [PATCH 08/37] fixup global object reference per domenic, improves #472 --- index.bs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.bs b/index.bs index cd006b61b..a2648e017 100644 --- a/index.bs +++ b/index.bs @@ -781,8 +781,7 @@ When this method is invoked, the user agent MUST execute the following algorithm Set |adjustedTimeout| to this adjusted value. If the {{PublicKeyCredentialRequestOptions/timeout}} member of |options| is [=present|not present=], then set |adjustedTimeout| to a platform-specific default. -1. Let |global| be the {{PublicKeyCredential}}'s [=interface object=]'s [=global object|environment settings object's global - object=]. +1. Let |global| be the {{PublicKeyCredential}}'s [=interface object=]'s [=relevant global object=]. 1. Let |callerOrigin| be the [=environment settings object/origin=] specified by this {{PublicKeyCredential}} [=interface object=]'s [=relevant settings object=]. If |callerOrigin| is an [=opaque origin=], return a {{DOMException}} whose name is From d492a505467c60f56830c430a4edc664afbdc975 Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 28 Jun 2017 15:41:29 -0700 Subject: [PATCH 09/37] indent 4.1.4 step 18et al to clarify relation to prior step --- index.bs | 93 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/index.bs b/index.bs index a2648e017..2d757dcde 100644 --- a/index.bs +++ b/index.bs @@ -913,55 +913,56 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Start a timer for |adjustedTimeout| milliseconds. Then execute the following steps [=in parallel=]. The [=task source=] for these [=tasks=] is the [=dom manipulation task source=]. -1. While |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer and - responses from the authenticators: - -
    - - : If the |adjustedTimeout| timer expires, - :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| - and [=set/remove=] |authenticator| from |issuedRequests|. - - : 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 - |authenticator| and [=set/remove=] it from |issuedRequests|. - - - : If any |authenticator| returns an error status, - :: [=set/Remove=] |authenticator| from |issuedRequests|. - - : If any |authenticator| indicates success, - :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. - 2. Let |value| be a new {{PublicKeyCredential}} associated with |global| whose fields are: + 1. While |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer + and responses from the authenticators: - : {{PublicKeyCredential/[[identifier]]}} - :: Create a new {{ArrayBuffer}}, using |global|'s [=%ArrayBuffer%=]. - If |savedCredentialId| exists, set the value of the new {{ArrayBuffer}} to be the bytes of - |savedCredentialId|. Otherwise, set the value of the new {{ArrayBuffer}} to be the bytes of the credential - ID returned from the successful [=authenticatorGetAssertion=] operation, as defined in - [[#op-get-assertion]]. - : {{PublicKeyCredential/response}} - :: A new {{AuthenticatorAssertionResponse}} object associated with |global| whose fields are: - : {{AuthenticatorResponse/clientDataJSON}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of |clientDataJSON| - : {{AuthenticatorAssertionResponse/authenticatorData}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned - {{authenticatorData}} - : {{AuthenticatorAssertionResponse/signature}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned - {{signature}} - : {{PublicKeyCredential/clientExtensionResults}} - :: A new {{AuthenticationExtensions}} object containing the [=extension identifier=] → [=client extension output=] - entries created by running each extension's [=client extension processing=] algorithm to create the [=client - extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. +
    - 3. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on - |authenticator| and [=set/remove=] it from |issuedRequests|. + : If the |adjustedTimeout| timer expires, + :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| + and [=set/remove=] |authenticator| from |issuedRequests|. + + : 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 + |authenticator| and [=set/remove=] it from |issuedRequests|. + + + : If any |authenticator| returns an error status, + :: [=set/Remove=] |authenticator| from |issuedRequests|. + + : If any |authenticator| indicates success, + :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. + 2. Let |value| be a new {{PublicKeyCredential}} associated with |global| whose fields are: + + : {{PublicKeyCredential/[[identifier]]}} + :: Create a new {{ArrayBuffer}}, using |global|'s [=%ArrayBuffer%=]. + If |savedCredentialId| exists, set the value of the new {{ArrayBuffer}} to be the bytes of + |savedCredentialId|. Otherwise, set the value of the new {{ArrayBuffer}} to be the bytes of the + credential ID returned from the successful [=authenticatorGetAssertion=] operation, as defined in + [[#op-get-assertion]]. + : {{PublicKeyCredential/response}} + :: A new {{AuthenticatorAssertionResponse}} object associated with |global| whose fields are: + : {{AuthenticatorResponse/clientDataJSON}} + :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of + |clientDataJSON| + : {{AuthenticatorAssertionResponse/authenticatorData}} + :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned + {{authenticatorData}} + : {{AuthenticatorAssertionResponse/signature}} + :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned + {{signature}} + : {{PublicKeyCredential/clientExtensionResults}} + :: A new {{AuthenticationExtensions}} object containing the [=extension identifier=] → [=client extension + output=] entries created by running each extension's [=client extension processing=] algorithm to create the + [=client extension outputs=], for each [=client extension=] in + {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. + + 3. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on + |authenticator| and [=set/remove=] it from |issuedRequests|. + 4. Return |value| and terminate this algorithm. - 4. Return |value| and terminate this algorithm. - -
    +
    1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". From 2934f9e1199a49e9094aa74741e1597d8404fcec Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 28 Jun 2017 15:42:33 -0700 Subject: [PATCH 10/37] fix line indent --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 2d757dcde..00cb31090 100644 --- a/index.bs +++ b/index.bs @@ -945,7 +945,7 @@ When this method is invoked, the user agent MUST execute the following algorithm :: A new {{AuthenticatorAssertionResponse}} object associated with |global| whose fields are: : {{AuthenticatorResponse/clientDataJSON}} :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of - |clientDataJSON| + |clientDataJSON| : {{AuthenticatorAssertionResponse/authenticatorData}} :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned {{authenticatorData}} From a1be0f6a3ccd800020da6c4afc4a13d6e9cba765 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 18 Aug 2017 14:12:37 -0700 Subject: [PATCH 11/37] post rebase-on-master, fix dangling MakeCredentialOptions --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 00cb31090..b4baf8f50 100644 --- a/index.bs +++ b/index.bs @@ -687,7 +687,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Otherwise, [=list/Append=] |C| to |excludeCredentialDescriptorList|. 1. [=In parallel=], invoke the [=authenticatorMakeCredential=] operation on |authenticator| with - |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakeCredentialOptions/user}}, + |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, |normalizedParameters|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. 1. [=set/Append=] |authenticator| to |issuedRequests|. From 28f52af95fb51fa8bdc5825a739fc9c1e6fd9949 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 18 Aug 2017 14:29:26 -0700 Subject: [PATCH 12/37] fix error in resolving rebase conflicts --- index.bs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index b4baf8f50..39f9c14fe 100644 --- a/index.bs +++ b/index.bs @@ -687,8 +687,13 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Otherwise, [=list/Append=] |C| to |excludeCredentialDescriptorList|. 1. [=In parallel=], invoke the [=authenticatorMakeCredential=] operation on |authenticator| with - |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, - |normalizedParameters|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. + |clientDataHash|, + |options|.{{MakePublicKeyCredentialOptions/rp}}, + |options|.{{MakePublicKeyCredentialOptions/user}}, + |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/rk}}, + |credTypesAndPubKeyAlgs|, + |excludeCredentialDescriptorList|, + and |authenticatorExtensions| as parameters. 1. [=set/Append=] |authenticator| to |issuedRequests|. From 5fada185c4d0e84634df6eeb3182d0def50f56b7 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 18 Aug 2017 14:40:32 -0700 Subject: [PATCH 13/37] further rebase conflict resolution error fixups --- index.bs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.bs b/index.bs index 39f9c14fe..f8f1a6cb1 100644 --- a/index.bs +++ b/index.bs @@ -611,14 +611,14 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Let |credTypesAndPubKeyAlgs| be a new [=list=] whose [=list/items=] are pairs of {{PublicKeyCredentialType}} and a {{COSEAlgorithmIdentifier}}. -1. [=list/For each=] |current| of |options|.{{MakePublicKeyCredentialOptions/parameters}}: +1. [=list/For each=] |current| of |options|.{{MakePublicKeyCredentialOptions/pubKeyCredParams}}: 1. If |current|.{{PublicKeyCredentialParameters/type}} does not contain a {{PublicKeyCredentialType}} supported by this implementation, then [=continue=]. 1. Let |alg| be |current|.{{PublicKeyCredentialParameters/alg}}. 1. [=list/Append=] the pair of |current|.{{PublicKeyCredentialParameters/type}} and |alg| to |credTypesAndPubKeyAlgs|. -1. If |normalizedParameters| [=list/is empty=] and |options|.{{MakePublicKeyCredentialOptions/parameters}} +1. If |credTypesAndPubKeyAlgs| [=list/is empty=] and |options|.{{MakePublicKeyCredentialOptions/pubKeyCredParams}} [=list/is not empty=], cancel the timer started in step 2, return a {{DOMException}} whose name is "{{NotSupportedError}}", and terminate this algorithm. @@ -738,7 +738,7 @@ When this method is invoked, the user agent MUST execute the following algorithm : {{PublicKeyCredential/clientExtensionResults}} :: A new {{AuthenticationExtensions}} object containing the [=extension identifier=] → [=client extension output=] entries created by running each extension's [=client extension processing=] algorithm to create the [=client - extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. + extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. 5. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] it from |issuedRequests|. From 5fb2f8c47b5d106108864f0fb30cd310dbfc70b9 Mon Sep 17 00:00:00 2001 From: JeffH Date: Tue, 22 Aug 2017 13:26:05 -0700 Subject: [PATCH 14/37] convert switch steps to colon-denotation --- index.bs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/index.bs b/index.bs index e0e0a4b3b..fb7c04ade 100644 --- a/index.bs +++ b/index.bs @@ -705,23 +705,20 @@ When this method is invoked, the user agent MUST execute the following algorithm responses from the authenticators:
    -
    If the |adjustedTimeout| timer expires,
    -
    [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| + : If the |adjustedTimeout| timer expires, + :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|.
    -
    If any |authenticator| returns a status indicating that the user cancelled the operation,
    -
    - 1. [=set/Remove=] |authenticator| from |issuedRequests|. + : 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 |authenticator| and [=set/remove=] it from |issuedRequests|. -
    -
    If any |authenticator| returns an error status,
    -
    [=set/Remove=] |authenticator| from |issuedRequests|.
    + : If any |authenticator| returns an error status, + :: [=set/Remove=] |authenticator| from |issuedRequests|. -
    If any |authenticator| indicates success,
    -
    - 1. [=set/Remove=] |authenticator| from |issuedRequests|. + : If any |authenticator| indicates success, + :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. 2. Let |attestationObject| be a new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the value returned from the successful [=authenticatorMakeCredential=] operation (which is attObj, as defined in [[#generating-an-attestation-object]]). @@ -744,7 +741,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 5. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] it from |issuedRequests|. 6. Return |value| and terminate this algorithm. -
    +
    1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". From 51706b3bd4ffec19097df9803f923b0efd1864f5 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 24 Aug 2017 14:24:56 -0700 Subject: [PATCH 15/37] tag 'while' --- index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index fb7c04ade..213dc27ec 100644 --- a/index.bs +++ b/index.bs @@ -701,8 +701,8 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Start a timer for |adjustedTimeout| milliseconds. Then execute the following steps [=in parallel=]. The [=task source=] for these [=tasks=] is the [=dom manipulation task source=]. -1. While |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer and - responses from the authenticators: +1. [=While=] |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer + and responses from the authenticators:
    : If the |adjustedTimeout| timer expires, From 5e4a7b0cdcbe111fe261ba59b3ad29ca8bd30443 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 24 Aug 2017 20:01:57 -0700 Subject: [PATCH 16/37] primary changes for improving #472 mostly complete --- index.bs | 101 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 22 deletions(-) diff --git a/index.bs b/index.bs index 213dc27ec..dbf50d1ed 100644 --- a/index.bs +++ b/index.bs @@ -96,6 +96,7 @@ spec: credential-management-1; urlPrefix: https://w3c.github.io/webappsec-creden
    @@ -751,6 +765,49 @@ authorizing an authenticator. +#### Construct the resultant credential - `constructResultantCredentialCallback` algorithm #### {#constructResultantCredentialCallback} + +[=constructResultantCredentialCallback=] is a Web IDL {{Function}} [=callback function type=] value. +Its purpose is to map |credentialCreationData|'s [=items=] into a new {{PublicKeyCredential}} object associated with the +caller's [=environment settings object/global object=], while running on the main [=event loop=]. See also +[[!CREDENTIAL-MANAGEMENT-1]]. + +When [=constructResultantCredentialCallback=] is invoked, given [=credentialCreationDataInstance=], (whose value is +the [=struct=] |credentialCreationData| as defined in [[#createCredential]], above) and |global| (its caller's +[=current settings object=]'s [=environment settings object/global object=]), run these steps: + +1. Let |attestationObject| be a new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the + bytes of |credentialCreationData|.[=attestationObjectResult=]'s value. + +3. Let |id| be |attestationObject|.authData.attestation data.credential ID (see [[#sec-attestation-data]] + and [[#sec-authenticator-data]]). + +4. Let |pubKeyCred| be a new {{PublicKeyCredential}} object associated with |global| whose fields are: + + : {{PublicKeyCredential/[[identifier]]}} + :: |id| + + : {{PublicKeyCredential/response}} + :: A new {{AuthenticatorAttestationResponse}} object associated with |global| whose fields are: + + : {{AuthenticatorResponse/clientDataJSON}} + :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of + |credentialCreationData|.[=clientDataJSONResult=]. + + : {{AuthenticatorAttestationResponse/attestationObject}} + :: |attestationObject| + + : {{PublicKeyCredential/clientExtensionResults}} + :: A new {{AuthenticationExtensions}} object associated with |global| containing the bytes + of |credentialCreationData|.[=extensionOutputsMap=]'s value. + + Note: |credentialCreationData|.[=extensionOutputsMap=] is an [=ordered map=] whose [=map/keys=] are all + of type [=extension identifiers=] and [=map/values=] are all of type [=client extension output=]. Thus the + latter is implicitly a [=record type=], which is the {{AuthenticationExtensions}}'s type. + +5. Return |pubKeyCred|. + + ### Use an existing credential to make an assertion - PublicKeyCredential's `[[DiscoverFromExternalSource]](options)` method ### {#getAssertion}
    From d6d6c191462e1d95d19a8b64cde26baf4ff43e83 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 24 Aug 2017 20:05:35 -0700 Subject: [PATCH 17/37] further issue #472 cleanups --- index.bs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/index.bs b/index.bs index dbf50d1ed..c741ca3db 100644 --- a/index.bs +++ b/index.bs @@ -688,7 +688,7 @@ When this method is invoked, the user agent MUST execute the following algorithm mentioned in |C|.{{transports}}, the client MAY [=continue=]. 1. Otherwise, [=list/Append=] |C| to |excludeCredentialDescriptorList|. - 1. [=In parallel=], invoke the [=authenticatorMakeCredential=] operation on |authenticator| with + 1. Invoke the [=authenticatorMakeCredential=] operation on |authenticator| with |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, @@ -699,8 +699,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. [=set/Append=] |authenticator| to |issuedRequests|. -1. Start a timer for |adjustedTimeout| milliseconds. Then execute the following steps [=in parallel=]. The [=task source=] for - these [=tasks=] is the [=dom manipulation task source=]. +1. Start a timer for |adjustedTimeout| milliseconds. 1. [=While=] |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer and responses from the authenticators: From a76de0b480fedd4f4e86de0e51d2d845f5259195 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 24 Aug 2017 20:08:49 -0700 Subject: [PATCH 18/37] del 'cancel the timer' from #creatCredential fixes #535 --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index c741ca3db..9c45ad0af 100644 --- a/index.bs +++ b/index.bs @@ -621,7 +621,7 @@ When this method is invoked, the user agent MUST execute the following algorithm |credTypesAndPubKeyAlgs|. 1. If |credTypesAndPubKeyAlgs| [=list/is empty=] and |options|.{{MakePublicKeyCredentialOptions/pubKeyCredParams}} - [=list/is not empty=], cancel the timer started in step 2, return a {{DOMException}} whose name is "{{NotSupportedError}}", + [=list/is not empty=], return a {{DOMException}} whose name is "{{NotSupportedError}}", and terminate this algorithm. 1. Let |clientExtensions| be a new [=map=] and let |authenticatorExtensions| be a new [=map=]. From 97f0ae249ee404effcdfaac9b49b4bc17873cc32 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 24 Aug 2017 20:32:11 -0700 Subject: [PATCH 19/37] polish constructResultantCredentialCallback method description --- index.bs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/index.bs b/index.bs index 9c45ad0af..d8f895cef 100644 --- a/index.bs +++ b/index.bs @@ -699,7 +699,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. [=set/Append=] |authenticator| to |issuedRequests|. -1. Start a timer for |adjustedTimeout| milliseconds. +1. Start a timer for |adjustedTimeout| milliseconds. 1. [=While=] |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer and responses from the authenticators: @@ -764,16 +764,21 @@ authorizing an authenticator.
    -#### Construct the resultant credential - `constructResultantCredentialCallback` algorithm #### {#constructResultantCredentialCallback} +#### Construct the resultant credential - `constructResultantCredentialCallback` method #### {#constructResultantCredentialCallback} -[=constructResultantCredentialCallback=] is a Web IDL {{Function}} [=callback function type=] value. -Its purpose is to map |credentialCreationData|'s [=items=] into a new {{PublicKeyCredential}} object associated with the -caller's [=environment settings object/global object=], while running on the main [=event loop=]. See also +This method's purpose is to map |credentialCreationData|'s [=items=] into a new {{PublicKeyCredential}} object associated +with the caller's [=environment settings object/global object=], while running on the main [=event loop=]. See also [[!CREDENTIAL-MANAGEMENT-1]]. -When [=constructResultantCredentialCallback=] is invoked, given [=credentialCreationDataInstance=], (whose value is -the [=struct=] |credentialCreationData| as defined in [[#createCredential]], above) and |global| (its caller's -[=current settings object=]'s [=environment settings object/global object=]), run these steps: +This algorithm accepts two arguments: + + : [=credentialCreationDataInstance=] + :: whose value is the [=struct=] |credentialCreationData| as defined in [[#createCredential]], above. + + : |global| + :: Which must be its caller's [=current settings object=]'s [=environment settings object/global object=]. + +When this method is invoked, the user agent MUST execute the following algorithm: 1. Let |attestationObject| be a new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of |credentialCreationData|.[=attestationObjectResult=]'s value. From 8622aeafcf0c223a5fbc2727177850eb1aee1ba0 Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Thu, 31 Aug 2017 11:57:55 -0700 Subject: [PATCH 20/37] marked authenticator model section as non-normative --- index.bs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.bs b/index.bs index d8f895cef..4138e1949 100644 --- a/index.bs +++ b/index.bs @@ -1536,6 +1536,8 @@ the {{CredentialsContainer/create()}} or {{CredentialsContainer/get()}} methods. # WebAuthn Authenticator model # {#authenticator-model} +[INFORMATIVE] + The API defined in this specification implies a specific abstract functional model for an [=authenticator=]. This section describes the authenticator model. From e8ca2bea1c543041a5aea8a9f7f3edc759fe291f Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Thu, 31 Aug 2017 12:00:35 -0700 Subject: [PATCH 21/37] marked relying party operation section as non-normative --- index.bs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.bs b/index.bs index 4138e1949..257c8c5ac 100644 --- a/index.bs +++ b/index.bs @@ -2082,6 +2082,8 @@ should be specified in the attestation certificate itself, so that it can be ver # [=[RP]=] Operations # {#rp-operations} +[INFORMATIVE] + Upon successful execution of {{CredentialsContainer/create()}} or {{CredentialsContainer/get()}}, the [=[RP]=]'s script receives a {{PublicKeyCredential}} containing an {{AuthenticatorAttestationResponse}} or {{AuthenticatorAssertionResponse}} structure, respectively, from the client. It must then deliver the contents of this structure to the [=[RP]=] server, using methods outside From 84c12bb2de03b1b78033a5677671cac969bb95e4 Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Thu, 31 Aug 2017 15:42:26 -0700 Subject: [PATCH 22/37] fix proper subset tweak --- index.bs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index 725db36ea..ed17c1f2c 100644 --- a/index.bs +++ b/index.bs @@ -2022,8 +2022,8 @@ When registering a new credential, represented by a {{AuthenticatorAttestationRe 4. Verify that the {{CollectedClientData/tokenBindingId}} in |C| matches the [=Token Binding ID=] for the TLS connection over which the attestation was obtained. -5. Verify that the {{CollectedClientData/clientExtensions}} in |C| is a proper subset of the extensions requested by the RP - and that the {{CollectedClientData/authenticatorExtensions}} in |C| is also a proper subset of the extensions requested by +5. Verify that the {{CollectedClientData/clientExtensions}} in |C| is a subset of the extensions requested by the RP + and that the {{CollectedClientData/authenticatorExtensions}} in |C| is also a subset of the extensions requested by the RP. 6. Compute the hash of {{AuthenticatorResponse/clientDataJSON}} using the algorithm identified by @@ -2104,8 +2104,8 @@ When verifying a given {{PublicKeyCredential}} structure (|credential|) as part 6. Verify that the {{CollectedClientData/tokenBindingId}} member of |C| (if present) matches the [=Token Binding ID=] for the TLS connection over which the signature was obtained. -7. Verify that the {{CollectedClientData/clientExtensions}} member of |C| is a proper subset of the extensions requested by the - [=[RP]=] and that the {{CollectedClientData/authenticatorExtensions}} in |C| is also a proper subset of the extensions +7. Verify that the {{CollectedClientData/clientExtensions}} member of |C| is a subset of the extensions requested by the + [=[RP]=] and that the {{CollectedClientData/authenticatorExtensions}} in |C| is also a subset of the extensions requested by the [=[RP]=]. 8. Verify that the [=RP ID=] hash in |aData| is the SHA-256 hash of the [=RP ID=] expected by the [=[RP]=]. From 22638883503f174a5d9dcd64d1e5cbdcd4707d8f Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Tue, 5 Sep 2017 16:57:47 -0700 Subject: [PATCH 23/37] Added abort signal object and steps to webauthn --- index.bs | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/index.bs b/index.bs index 257c8c5ac..471988e4b 100644 --- a/index.bs +++ b/index.bs @@ -53,6 +53,10 @@ Markup Shorthands: css off, markdown on
     
    +spec: DOM; urlPrefix: https://dom.spec.whatwg.org/
    +    type: interface
    +        text: AbortSignal; url: #abortsignal
    +
     spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/#
         type: method
             for: JSON; text: stringify; url: sec-json.stringify
    @@ -539,7 +543,8 @@ 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=]. The user agent will prompt the user for [=user consent|consent=].
     On success, the returned {{promise}} will be resolved with a {{PublicKeyCredential}} containing an
    -{{AuthenticatorAttestationResponse}} object.
    +{{AuthenticatorAttestationResponse}} object. This method can be terminated 
    +with flag [=AbortSignal/aborted flag=], which is unset unless otherwise specificed.
     
     Note: This algorithm is synchronous; the {{Promise}} resolution/rejection is handled by
     {{CredentialsContainer/create()|navigator.credentials.create()}}.
    @@ -701,14 +706,20 @@ When this method is invoked, the user agent MUST execute the following algorithm
     
     1. Start a timer for |adjustedTimeout| milliseconds.
     
    -1. [=While=] |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer
    -    and responses from the authenticators:
    +1. [=While=] |issuedRequests| [=list/is not empty=], perform the following actions in parallel depending upon the |adjustedTimeout| 
    +    timer and responses from the authenticators but abort if the operation is [=terminated=]:
         
    : If the |adjustedTimeout| timer expires, :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. + : If the |options|.{{MakePublicKeyCredentialOptions/signal}} is [=present=] and and the + [=AbortSignal/aborted flag=] is set to false, + :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| + and [=set/remove=] |authenticator| from |issuedRequests|. Set the [=AbortSignal/aborted flag=] be true. Then + reject the promise with an {{AbortError}} {{DOMException}}. + : 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 @@ -974,8 +985,8 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. [=set/Append=] |authenticator| to |issuedRequests|. -1. Start a timer for |adjustedTimeout| milliseconds. Then execute the following steps [=in parallel=]. The [=task source=] for - these [=tasks=] is the [=dom manipulation task source=]. +1. Start a timer for |adjustedTimeout| milliseconds. Then execute the following steps [=in parallel=] but abort if the steps are + [=terminated=]. The [=task source=] for these [=tasks=] is the [=dom manipulation task source=]. 1. While |issuedRequests| [=list/is not empty=], perform the following actions depending upon the |adjustedTimeout| timer and responses from the authenticators: @@ -986,12 +997,17 @@ 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 {{PublicKeyCredentialRequestOptions/signal}} member is [=present=] and the [=AbortSignal/aborted flag=] is set to + false, + :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| + and [=set/remove=] |authenticator| from |issuedRequests|. Set the [=AbortSignal/aborted flag=] be true. Then + reject the promise with an {{AbortError}} {{DOMException}}. + : 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 |authenticator| and [=set/remove=] it from |issuedRequests|. - : If any |authenticator| returns an error status, :: [=set/Remove=] |authenticator| from |issuedRequests|. @@ -1184,6 +1200,7 @@ optionally evidence of [=user consent=] to a specific transaction. unsigned long timeout; sequence excludeCredentials = []; AuthenticatorSelectionCriteria authenticatorSelection; + AbortSignal signal; AuthenticationExtensions extensions; }; @@ -1234,6 +1251,11 @@ optionally evidence of [=user consent=] to a specific transaction. :: This member is intended for use by [=[RPS]=] that wish to select the appropriate authenticators to participate in the {{CredentialsContainer/create()}} or {{CredentialsContainer/get()}} operation. + : signal + :: This member is intended to be used by developers to [=terminated|terminate=] an + ongoing {{PublicKeyCredential/[[Create]](options)/options}} operation. The object is initially a new AbortSignal + object. + : extensions :: This member contains additional parameters requesting additional processing by the client and authenticator. For example, the caller may request that only authenticators with certain capabilies be used to create the credential, or @@ -1366,6 +1388,7 @@ an assertion. Its {{PublicKeyCredentialRequestOptions/challenge}} member must be unsigned long timeout; USVString rpId; sequence allowCredentials = []; + AbortSignal signal; AuthenticationExtensions extensions; }; @@ -1389,6 +1412,11 @@ an assertion. Its {{PublicKeyCredentialRequestOptions/challenge}} member must be 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). + : signal + :: This member is intended to be used by developers to [=terminated|terminate=] an ongoing + {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)/options}} operation. The object is initially a new + AbortSignal object. + : 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 From fa7c06b196cbc557737111f7e0f1d893010f5f55 Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Wed, 25 Oct 2017 09:42:41 -0700 Subject: [PATCH 24/37] fixed a minor issue with linking --- index.bs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.bs b/index.bs index a0ab7b80d..b949b4c66 100644 --- a/index.bs +++ b/index.bs @@ -52,6 +52,7 @@ Markup Shorthands: css off, markdown on
    +
     spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/#
         type: method
             for: JSON; text: stringify; url: sec-json.stringify
    @@ -135,7 +136,7 @@ is [=Registration=], where a [=public key credential=] is created on an [=authen
     with the present user's account (the account may already exist or may be created at this time). The second is
     [=Authentication=], where the [=[RP]=] is presented with an [=Authentication Assertion=] proving the presence
     and consent of the user who registered the [=public key credential=]. Functionally, the [=Web Authentication API=] comprises
    -a {{PublicKeyCredential}} which extends the Credential Management API [[CREDENTIAL-MANAGEMENT-1]], and infrastructure which
    +a {{PublicKeyCredential}} which extends the Credential Management API [[!CREDENTIAL-MANAGEMENT-1]], and infrastructure which
     allows those credentials to be used with {{CredentialsContainer/create()|navigator.credentials.create()}} and
     {{CredentialsContainer/get()|navigator.credentials.get()}}. The former is used during [=Registration=], and the
     latter during [=Authentication=].
    
    From 6181caf7e1796097bd1aa71e407435f5499e5839 Mon Sep 17 00:00:00 2001
    From: Angelo Liao 
    Date: Thu, 26 Oct 2017 12:47:50 -0700
    Subject: [PATCH 25/37] add minor edits to focus on the main things
    
    ---
     index.bs | 3 ---
     1 file changed, 3 deletions(-)
    
    diff --git a/index.bs b/index.bs
    index 1c0e2446c..f34026573 100644
    --- a/index.bs
    +++ b/index.bs
    @@ -52,7 +52,6 @@ Markup Shorthands: css off, markdown on
     
    -
     spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/#
         type: method
             for: JSON; text: stringify; url: sec-json.stringify
    @@ -2214,8 +2213,6 @@ should be specified in the attestation certificate itself, so that it can be ver
     
     # [=[RP]=] Operations # {#rp-operations}
     
    -[INFORMATIVE]
    -
     Upon successful execution of {{CredentialsContainer/create()}} or {{CredentialsContainer/get()}}, the [=[RP]=]'s script receives
     a {{PublicKeyCredential}} containing an {{AuthenticatorAttestationResponse}} or {{AuthenticatorAssertionResponse}} structure,
     respectively, from the client. It must then deliver the contents of this structure to the [=[RP]=] server, using methods outside
    
    From 0d5bba14ae6c5e62877132c9a05bfa2af0ac734b Mon Sep 17 00:00:00 2001
    From: Angelo Liao 
    Date: Thu, 26 Oct 2017 12:58:47 -0700
    Subject: [PATCH 26/37] getting the blank line correct
    
    ---
     index.bs | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/index.bs b/index.bs
    index f34026573..676f54bf4 100644
    --- a/index.bs
    +++ b/index.bs
    @@ -52,6 +52,7 @@ Markup Shorthands: css off, markdown on
     
    +
     spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/#
         type: method
             for: JSON; text: stringify; url: sec-json.stringify
    
    From 352223c2300cf795e93c15b9f335f2a0e62f2f19 Mon Sep 17 00:00:00 2001
    From: Angelo Liao 
    Date: Mon, 30 Oct 2017 12:04:51 -0700
    Subject: [PATCH 27/37] Added a example section to explain how abort should be
     used
    
    ---
     index.bs | 33 +++++++++++++++++++++++++++++++++
     1 file changed, 33 insertions(+)
    
    diff --git a/index.bs b/index.bs
    index 676f54bf4..4a9efdc7c 100644
    --- a/index.bs
    +++ b/index.bs
    @@ -3779,6 +3779,39 @@ extension for transaction authorization.
         });
     
    +## Aborting Authentication Operations ## {#sample-aborting} + +The below example showcases how a developer may use the AbortSignal parameter to abort an +ongoing credential registration operation. Similiar procedure applies to an ongoing +authentication operation. + +
    +    const authAbortController = new AbortController(); 
    +    const authAbortSignal = controller.signal;
    +
    +    var options = {
    +        // A list  of options. 
    +    }
    +
    +    navigator.credentials.create({"publicKey": options}, authAbortSignal)
    +        .then(function (attestation) {
    +            // Register the user. 
    +        }).catch(function (error) {
    +            if (error = "AbortError") {
    +                // Let the server know a key hasn't been created. 
    +            }
    +        });
    +
    +    // Assume widget shows up whenever auth occurs. 
    +    if (widget = "disappear") {
    +        authAbortSignal.abort(); 
    +
    +        authAbortSignal.onabort = function () {
    +            // Migrate away from the page and other necessary clean-ups. 
    +        }
    +    }
    +
    + ## Decommissioning ## {#sample-decommissioning} From 298677fe41d6cebf59401b36d49d8ab0a4413436 Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Wed, 1 Nov 2017 01:30:53 -0700 Subject: [PATCH 28/37] fix up example --- index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index 4a9efdc7c..ec148a054 100644 --- a/index.bs +++ b/index.bs @@ -1795,7 +1795,7 @@ session to exist at any particular time, or by providing more complicated sessio The following operations can be invoked by the client in an authenticator session. -

    The authenticatorMakeCredential operation

    +

    The authenticatorMakeCredential operation

    This operation must be invoked in an authenticator session which has no other operations in progress. It takes the following input parameters: @@ -3793,7 +3793,7 @@ authentication operation. // A list of options. } - navigator.credentials.create({"publicKey": options}, authAbortSignal) + navigator.credentials.create({"publicKey": options, authAbortSignal}) .then(function (attestation) { // Register the user. }).catch(function (error) { From 549e659efa756a564f402dd3a81cdd6705a94304 Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Wed, 1 Nov 2017 01:59:42 -0700 Subject: [PATCH 29/37] committing before computer dies --- index.bs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index ec148a054..dddf8c68f 100644 --- a/index.bs +++ b/index.bs @@ -101,6 +101,7 @@ spec: mixed-content; urlPrefix: www.w3.org/TR/mixed-content/ spec:credential-management; type:dfn; text:credentials spec:html; type:dfn; for:environment settings object; text:global object spec:infra; type:dfn; text:list +spec:infra; type:dfn; for:struct; text:item spec:url; type:dfn; text:domain spec:url; type:dfn; for:url; text:host spec:url; type:dfn; text:valid domain; @@ -569,8 +570,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. This method can be terminated -with flag [=AbortSignal/aborted flag=], which is unset unless otherwise specificed. +{{AuthenticatorAttestationResponse}} object. If an {{AbortSignal}} object is passed in, +the developer can abort on going {{CredentialsContainer/create()|navigator.credentials.create()}} operation with +the {{AbortController/abort()}} method. Note: This algorithm is synchronous; the {{Promise}} resolution/rejection is handled by {{CredentialsContainer/create()|navigator.credentials.create()}}. From ad5a888d6baccd1e33e811196a9f6d6e50d6ae75 Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Thu, 2 Nov 2017 12:37:04 -0700 Subject: [PATCH 30/37] updated grammars of the example based on feedback --- index.bs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/index.bs b/index.bs index dddf8c68f..3ad42e04c 100644 --- a/index.bs +++ b/index.bs @@ -3783,34 +3783,38 @@ extension for transaction authorization. ## Aborting Authentication Operations ## {#sample-aborting} -The below example showcases how a developer may use the AbortSignal parameter to abort an -ongoing credential registration operation. Similiar procedure applies to an ongoing +The below example shows how a developer may use the AbortSignal parameter to abort an +ongoing credential registration operation. A similiar procedure applies to an ongoing authentication operation.
         const authAbortController = new AbortController(); 
    -    const authAbortSignal = controller.signal;
    +    const authAbortSignal = authAbortController.signal;
    +
    +    authAbortSignal.onabort = function () {
    +        // Migrate away from the page and other necessary clean-ups. 
    +    }
     
         var options = {
    -        // A list  of options. 
    +        // A list of options. 
         }
     
    -    navigator.credentials.create({"publicKey": options, authAbortSignal})
    +    navigator.credentials.create({
    +        publicKey: options, 
    +        signal: authAbortSignal})
             .then(function (attestation) {
                 // Register the user. 
             }).catch(function (error) {
    -            if (error = "AbortError") {
    +            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") {
    +    if (widget == "disappear") {
             authAbortSignal.abort(); 
     
    -        authAbortSignal.onabort = function () {
    -            // Migrate away from the page and other necessary clean-ups. 
    -        }
         }
     
    From c142b5a271b316be28ff8078b5a38b750f2968ba Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Thu, 2 Nov 2017 12:42:02 -0700 Subject: [PATCH 31/37] update example text --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 3ad42e04c..066ae9bca 100644 --- a/index.bs +++ b/index.bs @@ -3792,7 +3792,7 @@ authentication operation. const authAbortSignal = authAbortController.signal; authAbortSignal.onabort = function () { - // Migrate away from the page and other necessary clean-ups. + // Once the page knows the abort started, inform user it is attempting to abort. } var options = { From 3fa4a3f0e4f1a5e3315e47315c8f7cac15805800 Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Fri, 3 Nov 2017 12:48:06 -0700 Subject: [PATCH 32/37] Updated with the section on switching tab; complete the PR --- index.bs | 58 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/index.bs b/index.bs index 066ae9bca..652322f0a 100644 --- a/index.bs +++ b/index.bs @@ -570,9 +570,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. If an {{AbortSignal}} object is passed in, -the developer can abort on going {{CredentialsContainer/create()|navigator.credentials.create()}} operation with -the {{AbortController/abort()}} method. +{{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()}}. @@ -690,6 +690,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 promise rejected with=] an "{{AbortError}}" + {{DOMException}}. + 1. Start |lifetimeTimer|. 1. Let |issuedRequests| be a new [=ordered set=]. @@ -737,11 +741,11 @@ 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|.{{MakePublicKeyCredentialOptions/signal}} is [=present=] and and the - [=AbortSignal/aborted flag=] is set to false, - :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| - and [=set/remove=] |authenticator| from |issuedRequests|. Set the [=AbortSignal/aborted flag=] be true. Then - reject the promise with an {{AbortError}} {{DOMException}}. + : 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 promise rejected with=] + an "{{AbortError}}" {{DOMException}}. : If any |authenticator| returns a status indicating that the user cancelled the operation, :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. @@ -914,6 +918,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 promise rejected with=] an "{{AbortError}}" + {{DOMException}}. + 1. Let |issuedRequests| be a new [=ordered set=]. 1. Let |authenticator| be a platform-specific handle whose value identifies an [=authenticator=]. @@ -982,7 +990,7 @@ method is invoked, the user agent MUST: 1. [=set/Append=] |authenticator| to |issuedRequests|. -1. Execute the following steps [=in parallel=] but abort if the steps are [=terminated=]. The [=task source=] for these [=tasks=] +1. Execute the following steps [=in parallel=]. The [=task source=] for these [=tasks=] is the [=dom manipulation task source=]. 1. While |issuedRequests| [=list/is not empty=], perform the following actions depending upon |lifetimeTimer| @@ -995,10 +1003,10 @@ method is invoked, the user agent MUST: |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. : If the {{PublicKeyCredentialRequestOptions/signal}} member is [=present=] and the [=AbortSignal/aborted flag=] is set to - false, + true, :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| - and [=set/remove=] |authenticator| from |issuedRequests|. Set the [=AbortSignal/aborted flag=] be true. Then - reject the promise with an {{AbortError}} {{DOMException}}. + and [=set/remove=] |authenticator| from |issuedRequests|. Then + return [=a promise rejected with=] an "{{AbortError}}" {{DOMException}}. : If any |authenticator| returns a status indicating that the user cancelled the operation, :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. @@ -1104,6 +1112,32 @@ but short enough that the dangling promise will still be resolved in a reasonabl +### Abort operations ### {#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 complicated inheritance and parallelization structure of the {{PublicKeyCredential/[[Create]](options)}} + and {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)}} methods, the algorithm 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 communication with [=authenticators=] start, and finally + in parallelized communication with [=authenticators=] to generate credentials. + +The [[=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. + [WHATWG HTML WG Issue #2711](https://github.com/whatwg/html/issues/2711) + ## Authenticator Responses (interface AuthenticatorResponse) ## {#iface-authenticatorresponse} From 14a7659406f049d515e084f27c3c19ceea9b9aa5 Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Fri, 3 Nov 2017 14:20:03 -0700 Subject: [PATCH 33/37] minor tweak --- index.bs | 78 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/index.bs b/index.bs index 652322f0a..b9d1b75dd 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
    +## 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}
    @@ -3817,9 +3824,8 @@ extension for transaction authorization.
     
     ## Aborting Authentication Operations ## {#sample-aborting}
     
    -The below example shows how a developer may use the AbortSignal parameter to abort an
    -ongoing credential registration operation. A similiar procedure applies to an ongoing
    -authentication operation. 
    +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(); 
    
    From 2cb344cfb5ab1e317868d3fc8ffcef44d47c9c89 Mon Sep 17 00:00:00 2001
    From: Angelo Liao 
    Date: Fri, 3 Nov 2017 14:25:09 -0700
    Subject: [PATCH 34/37] finished polishing the spec
    
    ---
     index.bs | 18 ++++--------------
     1 file changed, 4 insertions(+), 14 deletions(-)
    
    diff --git a/index.bs b/index.bs
    index b9d1b75dd..1488814f1 100644
    --- a/index.bs
    +++ b/index.bs
    @@ -754,7 +754,7 @@ When this method is invoked, the user agent MUST execute the following algorithm
             :   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 promise rejected with=] 
    +            operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. Then return [=a promise rejected with=] 
                 an "{{AbortError}}" {{DOMException}}.
     
             :   If any |authenticator| returns a status indicating that the user cancelled the operation,
    @@ -1000,8 +1000,7 @@ method is invoked, the user agent MUST:
     
         1. [=set/Append=] |authenticator| to |issuedRequests|.
     
    -1. Execute the following steps [=in parallel=]. The [=task source=] for these [=tasks=]
    -    is the [=dom manipulation task source=].
    +1. Execute the following steps [=in parallel=]. The [=task source=] for these [=tasks=] is the [=dom manipulation task source=].
     
         1. While |issuedRequests| [=list/is not empty=], perform the following actions depending upon |lifetimeTimer|
             and responses from the authenticators:
    @@ -1015,7 +1014,7 @@ method is invoked, the user agent MUST:
                 :   If the {{PublicKeyCredentialRequestOptions/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 
    +                and [=set/remove=] |authenticator| from |issuedRequests|. Then 
                     return [=a promise rejected with=] an "{{AbortError}}" {{DOMException}}.
     
                 :   If any |authenticator| returns a status indicating that the user cancelled the operation,
    @@ -1236,7 +1235,6 @@ optionally evidence of [=user consent=] to a specific transaction.
             unsigned long                                timeout;
             sequence      excludeCredentials = [];
             AuthenticatorSelectionCriteria               authenticatorSelection;
    -        AbortSignal                                  signal;
             AuthenticationExtensions                     extensions;
         };
     
    @@ -1285,9 +1283,6 @@ optionally evidence of [=user consent=] to a specific transaction.
         ::  This member is intended for use by [=[RPS]=] that wish to select the appropriate authenticators to participate in
             the {{CredentialsContainer/create()}} or {{CredentialsContainer/get()}} operation.
     
    -    :   signal
    -    ::  This member is intended for use by [=[RPS]=] to abort {{PublicKeyCredential/[[Create]](options)/options}} operations. 
    -
         :   extensions
         ::  This member contains additional parameters requesting additional processing by the client and authenticator. For
             example, the caller may request that only authenticators with certain capabilies be used to create the credential, or
    @@ -1432,7 +1427,6 @@ an assertion. Its {{PublicKeyCredentialRequestOptions/challenge}} member must be
             unsigned long                        timeout;
             USVString                            rpId;
             sequence allowCredentials = [];
    -        AbortSignal                          signal;
             AuthenticationExtensions             extensions;
         };
     
    @@ -1455,10 +1449,6 @@ 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).
    -
    -    :   signal
    -    ::  This member is intended for use by [=[RPS]=] to abort a 
    -        {{PublicKeyCredential/[[DiscoverFromExternalSource]](options)/options}} operation.
         
         :   extensions
         ::  This optional member contains additional parameters requesting additional processing by the client and authenticator.
    @@ -1838,7 +1828,7 @@ session to exist at any particular time, or by providing more complicated sessio
     The following operations can be invoked by the client in an authenticator session.
     
     
    -

    The authenticatorMakeCredential operation

    +

    The authenticatorMakeCredential operation

    This operation must be invoked in an authenticator session which has no other operations in progress. It takes the following input parameters: From 2430dcd66b06579db1c28be8c6eb40b4f1951daf Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Fri, 3 Nov 2017 14:30:09 -0700 Subject: [PATCH 35/37] whoops one leftover --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 1488814f1..ceedff9f2 100644 --- a/index.bs +++ b/index.bs @@ -1011,7 +1011,7 @@ 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 {{PublicKeyCredentialRequestOptions/signal}} member is [=present=] and the [=AbortSignal/aborted flag=] is set to + : 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 From ad85e7591cebfb689fccda4296868651b2019319 Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Fri, 3 Nov 2017 14:46:41 -0700 Subject: [PATCH 36/37] finally figured out how to remove last two linking errors --- index.bs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.bs b/index.bs index ceedff9f2..a803caa46 100644 --- a/index.bs +++ b/index.bs @@ -557,6 +557,7 @@ the {{CredentialCreationOptions}} dictionary as follows:
         partial dictionary CredentialCreationOptions {
             MakePublicKeyCredentialOptions      publicKey;
    +        AbortSignal                         signal;
         };
     
    @@ -568,6 +569,7 @@ To support obtaining assertions via {{CredentialsContainer/get()|navigator.crede
         partial dictionary CredentialRequestOptions {
             PublicKeyCredentialRequestOptions      publicKey;
    +        AbortSignal                            signal;
         };
     
    @@ -1478,7 +1480,7 @@ The [=visibility states|visibility=] and [=focus=] state of the [=Window=] objec {{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. +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. From 78b091286a74a8dec0fd1393654f76f59494da2b Mon Sep 17 00:00:00 2001 From: Angelo Liao Date: Fri, 3 Nov 2017 16:23:20 -0700 Subject: [PATCH 37/37] take out abortsignal from extension; edit promise rejection --- index.bs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/index.bs b/index.bs index a803caa46..e34545481 100644 --- a/index.bs +++ b/index.bs @@ -557,7 +557,6 @@ the {{CredentialCreationOptions}} dictionary as follows:
         partial dictionary CredentialCreationOptions {
             MakePublicKeyCredentialOptions      publicKey;
    -        AbortSignal                         signal;
         };
     
    @@ -569,7 +568,6 @@ To support obtaining assertions via {{CredentialsContainer/get()|navigator.crede
         partial dictionary CredentialRequestOptions {
             PublicKeyCredentialRequestOptions      publicKey;
    -        AbortSignal                            signal;
         };
     
    @@ -703,8 +701,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 |options|.{{CredentialCreationOptions/signal}} is [=present=] and its - [=AbortSignal/aborted flag=] is set to true, return [=a promise rejected with=] an "{{AbortError}}" - {{DOMException}}. + [=AbortSignal/aborted flag=] is set to true, return a {{DOMException}} whose name is "{{AbortError}}" + and terminate this algorithm. 1. Start |lifetimeTimer|. @@ -756,8 +754,8 @@ When this method is invoked, the user agent MUST execute the following algorithm : 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 promise rejected with=] - an "{{AbortError}}" {{DOMException}}. + 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|. @@ -931,8 +929,8 @@ 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 promise rejected with=] an "{{AbortError}}" - {{DOMException}}. + [=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=]. @@ -1017,7 +1015,7 @@ method is invoked, the user agent MUST: true, :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. Then - return [=a promise rejected with=] an "{{AbortError}}" {{DOMException}}. + 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|.