From ed25b6c10864378b6843f1b1d167afa3628865de Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 16 Jun 2017 14:43:46 -0700 Subject: [PATCH 01/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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 1f096de96348f0a2889722d37735a08762cae9e1 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 7 Sep 2017 17:30:00 -0700 Subject: [PATCH 20/50] incorp comments from mikewest at webappsec-credential-management/pull/100 --- index.bs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/index.bs b/index.bs index d8f895cef..1c37e0f13 100644 --- a/index.bs +++ b/index.bs @@ -737,18 +737,20 @@ When this method is invoked, the user agent MUST execute the following algorithm 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. Let |value| be a [=struct=] whose [=items=] are: - - : constructResultantCredentialCallback - :: whose value is a Web IDL {{Function}} [=callback function type=] value implementing the - steps defined in [[#constructResultantCredentialCallback]]. + Issue: is there any special way to declare |credentialCreationData| such that it properly exists when + [=constructCredentialCallback=] (defined just below) is invoked? + - ISSUE: [=constructResultantCredentialCallback=] and - [=credentialCreationDataInstance=] should actually not be defined here (?) and link back - to their definitions in [[!CREDENTIAL-MANAGEMENT-1]] (?). + 3. Let |value| be a [=struct=] whose [=item=] is: + + : constructCredentialCallback + :: whose value is a Web IDL {{Function}} [=callback function type=] value implementing the + steps defined in [[#constructCredentialCallback]]. 5. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] it from |issuedRequests|. @@ -764,16 +766,13 @@ authorizing an authenticator. -#### Construct the resultant credential - `constructResultantCredentialCallback` method #### {#constructResultantCredentialCallback} +#### Construct the credential - `constructCredentialCallback` method #### {#constructCredentialCallback} 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]]. -This algorithm accepts two arguments: - - : [=credentialCreationDataInstance=] - :: whose value is the [=struct=] |credentialCreationData| as defined in [[#createCredential]], above. +This algorithm accepts one argument: : |global| :: Which must be its caller's [=current settings object=]'s [=environment settings object/global object=]. @@ -783,7 +782,7 @@ 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. -3. Let |id| be |attestationObject|.authData.attestation data.credential ID (see [[#sec-attestation-data]] +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: From ae91fa0aeccbbf7cbd719c4968b38dcbba7f0edb Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 29 Sep 2017 15:38:23 +1000 Subject: [PATCH 21/50] rebased onto master --- index.bs | 63 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/index.bs b/index.bs index 484353127..44e1cbc60 100644 --- a/index.bs +++ b/index.bs @@ -562,11 +562,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|.{{MakePublicKeyCredentialOptions/rp}}, the - {{PublicKeyCredentialEntity/name}} member of |options|.{{MakePublicKeyCredentialOptions/user}}, - the {{PublicKeyCredentialUserEntity/displayName}} member of |options|.{{MakePublicKeyCredentialOptions/user}}, - or the {{PublicKeyCredentialUserEntity/id}} - member of |options|.{{MakePublicKeyCredentialOptions/user}} are [=present|not present=], return a {{TypeError}} [=simple exception=]. +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=]. 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 @@ -588,38 +589,44 @@ 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}}.{{PublicKeyCredentialRpEntity/id}} is [=present=]: - 1. If |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialRpEntity/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. + 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. Set |rpId| to |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}. + : Is [=present|not present=] + :: Set |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} to + |effectiveDomain|. - 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}}.{{PublicKeyCredentialRpEntity/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 |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/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 |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. +1. If |credTypesAndPubKeyAlgs| [=list/is empty=] and |options|.{{MakePublicKeyCredentialOptions/pubKeyCredParams}} + [=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=]. @@ -663,7 +670,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|.{{MakeCredentialOptions/authenticatorSelection}} is [=present|present=], iterate through |currentlyAvailableAuthenticators| and do the following [=set/for each=] |authenticator|: 1. If {{AuthenticatorSelectionCriteria/authenticatorAttachment}} is [=present|present=] and its value is not equal to |authenticator|'s attachment modality, [=iteration/continue=]. @@ -680,14 +687,16 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. [=set/For each=] |authenticator| in |currentlyAvailableAuthenticators|: 1. Let |excludeCredentialDescriptorList| be a new [=list=]. + 1. [=list/For each=] credential descriptor |C| in |options|.{{MakePublicKeyCredentialOptions/excludeCredentials}}: 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/requireResidentKey}}, - |credTypesAndPubKeyAlgs|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. + + 1. 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|. 1. Start a timer for |adjustedTimeout| milliseconds. Then execute the following steps [=in parallel=]. The [=task source=] for @@ -731,7 +740,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|. @@ -1654,9 +1663,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 {{PublicKeyCredentialRpEntity}}. +- 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 79cff12954e9cc500db08064045ab579845998d1 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 16 Jun 2017 16:10:48 -0700 Subject: [PATCH 22/50] 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 44e1cbc60..efaac94fc 100644 --- a/index.bs +++ b/index.bs @@ -878,6 +878,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|. @@ -922,28 +926,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}} @@ -962,7 +967,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}}". @@ -1746,7 +1751,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 5fef555acebb4055b3c8f842827389baf361b10a Mon Sep 17 00:00:00 2001 From: JeffH Date: Tue, 20 Jun 2017 16:10:09 -0700 Subject: [PATCH 23/50] 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 efaac94fc..78d0591d3 100644 --- a/index.bs +++ b/index.bs @@ -788,8 +788,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 d55a65fe78691c77719ac3d1836af31ad46383b7 Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 28 Jun 2017 15:41:29 -0700 Subject: [PATCH 24/50] 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 78d0591d3..16685df20 100644 --- a/index.bs +++ b/index.bs @@ -920,54 +920,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 33bee9ec3d85ba213323d58c5e24f7acb5e18c9e Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 28 Jun 2017 15:42:33 -0700 Subject: [PATCH 25/50] fix line indent --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 16685df20..0d75ca580 100644 --- a/index.bs +++ b/index.bs @@ -952,7 +952,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 9872f1aa16acff9b55efb79794bfac8c87cf7c55 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 16 Jun 2017 14:43:46 -0700 Subject: [PATCH 26/50] do not call authenticatorMakeCredential() with separate |rpId| fixes #466 --- index.bs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/index.bs b/index.bs index 0d75ca580..fcfecf2dd 100644 --- a/index.bs +++ b/index.bs @@ -562,12 +562,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|.{{MakeCredentialOptions/rp}}, the - {{PublicKeyCredentialEntity/name}} member of |options|.{{MakeCredentialOptions/user}}, - the {{PublicKeyCredentialUserEntity/displayName}} member of |options|.{{MakeCredentialOptions/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|.{{MakeCredentialOptions/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 @@ -593,24 +592,24 @@ When this method is invoked, the user agent MUST execute the following algorithm -->
  • - If |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} + If |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}}
    : Is [=present=] - :: If |options|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} [=is not a + :: 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|.{{MakeCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} to + :: Set |options|.{{MakePublicKeyCredentialOptions/rp}}.{{PublicKeyCredentialEntity/id}} to |effectiveDomain|.
    - 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 + 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()}}.
  • @@ -670,7 +669,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|.{{MakePublicKeyCredentialOptions/authenticatorSelection}} is [=present|present=], iterate through |currentlyAvailableAuthenticators| and do the following [=set/for each=] |authenticator|: 1. If {{AuthenticatorSelectionCriteria/authenticatorAttachment}} is [=present|present=] and its value is not equal to |authenticator|'s attachment modality, [=iteration/continue=]. @@ -697,6 +696,11 @@ When this method is invoked, the user agent MUST execute the following algorithm |clientDataHash|, |options|.{{MakeCredentialOptions/rp}}, |options|.{{MakeCredentialOptions/user}}, |normalizedParameters|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. + 1. Invoke the [=authenticatorMakeCredential=] operation on |authenticator| with + |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, + |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/rk}}, + |credTypesAndPubKeyAlgs|, |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 From de00dfba1e30eb272fe759f0d10dd11459e0d439 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 16 Jun 2017 16:10:48 -0700 Subject: [PATCH 27/50] credID returned by authnrGetAssn() is optional if allowCreds has exactly 1 member fixes #472 --- index.bs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index fcfecf2dd..b7aba16e1 100644 --- a/index.bs +++ b/index.bs @@ -927,7 +927,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 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| @@ -938,7 +938,6 @@ When this method is invoked, the user agent MUST execute the following algorithm 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|. @@ -972,8 +971,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}}". From 8dc2fe6e41b755c835d108a83f96f9d325674be5 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 18 Aug 2017 14:12:37 -0700 Subject: [PATCH 28/50] post rebase-on-master, fix dangling MakeCredentialOptions --- index.bs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/index.bs b/index.bs index b7aba16e1..d23140279 100644 --- a/index.bs +++ b/index.bs @@ -692,10 +692,6 @@ 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. Invoke the [=authenticatorMakeCredential=] operation on |authenticator| with - |clientDataHash|, |options|.{{MakeCredentialOptions/rp}}, |options|.{{MakeCredentialOptions/user}}, - |normalizedParameters|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. - 1. Invoke the [=authenticatorMakeCredential=] operation on |authenticator| with |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/rk}}, From 1f7a9c604414c1beedf4c62d1aa8203f22cc3659 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 18 Aug 2017 14:29:26 -0700 Subject: [PATCH 29/50] fix error in resolving rebase conflicts --- index.bs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index d23140279..a925f7b40 100644 --- a/index.bs +++ b/index.bs @@ -616,7 +616,7 @@ 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/pubKeyCredParams}}: +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=]. @@ -693,9 +693,12 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Otherwise, [=list/Append=] |C| to |excludeCredentialDescriptorList|. 1. Invoke the [=authenticatorMakeCredential=] operation on |authenticator| with - |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, + |clientDataHash|, + |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/rk}}, - |credTypesAndPubKeyAlgs|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. + |credTypesAndPubKeyAlgs|, + |excludeCredentialDescriptorList|, + and |authenticatorExtensions| as parameters. 1. [=set/Append=] |authenticator| to |issuedRequests|. @@ -740,7 +743,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 8aeb8ed65e376825c64efa27411d4b74998b7607 Mon Sep 17 00:00:00 2001 From: JeffH Date: Tue, 22 Aug 2017 13:26:05 -0700 Subject: [PATCH 30/50] 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 a925f7b40..1e9966c7a 100644 --- a/index.bs +++ b/index.bs @@ -709,23 +709,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]]). @@ -748,7 +745,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 b6cf92213b24e5f80756336113b5d6dead92734d Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 24 Aug 2017 14:24:56 -0700 Subject: [PATCH 31/50] tag 'while' --- index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index 1e9966c7a..67dbb0058 100644 --- a/index.bs +++ b/index.bs @@ -705,8 +705,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 ef7b69d9f0f1c7a655246b930e1b3d5179604b75 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 24 Aug 2017 20:01:57 -0700 Subject: [PATCH 32/50] primary changes for improving #472 mostly complete --- index.bs | 93 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 18 deletions(-) diff --git a/index.bs b/index.bs index 67dbb0058..083a254af 100644 --- a/index.bs +++ b/index.bs @@ -100,6 +100,7 @@ spec: mixed-content; urlPrefix: www.w3.org/TR/mixed-content/
    @@ -755,6 +769,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 f5d75fe436bc12eccf45c1762bfe60e8eb8e9810 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 24 Aug 2017 20:05:35 -0700 Subject: [PATCH 33/50] further issue #472 cleanups --- index.bs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.bs b/index.bs index 083a254af..5b76192f6 100644 --- a/index.bs +++ b/index.bs @@ -703,8 +703,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 68ecbcef7d878b1fbb3dbd9179741eed031096d5 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 24 Aug 2017 20:32:11 -0700 Subject: [PATCH 34/50] polish constructResultantCredentialCallback method description --- index.bs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/index.bs b/index.bs index 5b76192f6..ec901427d 100644 --- a/index.bs +++ b/index.bs @@ -703,7 +703,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: @@ -768,16 +768,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 598c347eeb89a9a45ae175042c29b9797dfd3b03 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 7 Sep 2017 17:30:00 -0700 Subject: [PATCH 35/50] incorp comments from mikewest at webappsec-credential-management/pull/100 --- index.bs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/index.bs b/index.bs index ec901427d..f8095f7cd 100644 --- a/index.bs +++ b/index.bs @@ -741,18 +741,20 @@ When this method is invoked, the user agent MUST execute the following algorithm 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. Let |value| be a [=struct=] whose [=items=] are: - - : constructResultantCredentialCallback - :: whose value is a Web IDL {{Function}} [=callback function type=] value implementing the - steps defined in [[#constructResultantCredentialCallback]]. + Issue: is there any special way to declare |credentialCreationData| such that it properly exists when + [=constructCredentialCallback=] (defined just below) is invoked? + - ISSUE: [=constructResultantCredentialCallback=] and - [=credentialCreationDataInstance=] should actually not be defined here (?) and link back - to their definitions in [[!CREDENTIAL-MANAGEMENT-1]] (?). + 3. Let |value| be a [=struct=] whose [=item=] is: + + : constructCredentialCallback + :: whose value is a Web IDL {{Function}} [=callback function type=] value implementing the + steps defined in [[#constructCredentialCallback]]. 5. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] it from |issuedRequests|. @@ -768,16 +770,13 @@ authorizing an authenticator. -#### Construct the resultant credential - `constructResultantCredentialCallback` method #### {#constructResultantCredentialCallback} +#### Construct the credential - `constructCredentialCallback` method #### {#constructCredentialCallback} 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]]. -This algorithm accepts two arguments: - - : [=credentialCreationDataInstance=] - :: whose value is the [=struct=] |credentialCreationData| as defined in [[#createCredential]], above. +This algorithm accepts one argument: : |global| :: Which must be its caller's [=current settings object=]'s [=environment settings object/global object=]. @@ -787,7 +786,7 @@ 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. -3. Let |id| be |attestationObject|.authData.attestation data.credential ID (see [[#sec-attestation-data]] +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: From a1b998fbd34f9f98712b8ad66165bfdd6eb239cc Mon Sep 17 00:00:00 2001 From: JeffH Date: Sat, 30 Sep 2017 16:33:12 -0700 Subject: [PATCH 36/50] fix indents make BS happy, add some periods --- index.bs | 168 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 85 insertions(+), 83 deletions(-) diff --git a/index.bs b/index.bs index 4c1f4a4af..e9bbb1b97 100644 --- a/index.bs +++ b/index.bs @@ -93,7 +93,7 @@ spec: credential-management-1; urlPrefix: https://w3c.github.io/webappsec-creden text: create(); url: dom-credentialscontainer-create spec: mixed-content; urlPrefix: www.w3.org/TR/mixed-content/ - type: dfn + type: dfn text: a priori authenticated @@ -693,7 +693,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Otherwise, [=list/Append=] |C| to |excludeCredentialDescriptorList|. 1. Invoke the [=authenticatorMakeCredential=] operation on |authenticator| with - |clientDataHash|, + |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/rk}}, |credTypesAndPubKeyAlgs|, @@ -708,57 +708,57 @@ When this method is invoked, the user agent MUST execute the following algorithm 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 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 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 |credentialCreationData| be a [=struct=] whose [=items=] are: + 2. Let |credentialCreationData| be a [=struct=] whose [=items=] are: - : attestationObjectResult - :: whose value is the bytes returned from the successful [=authenticatorMakeCredential=] operation. + : attestationObjectResult + :: whose value is the bytes returned from the successful [=authenticatorMakeCredential=] operation. - Note: this value is attObj, as defined in [[#generating-an-attestation-object]]. + Note: this value is attObj, as defined in [[#generating-an-attestation-object]]. - : clientDataJSONResult - :: whose value is the bytes of |clientDataJSON|. + : clientDataJSONResult + :: whose value is the bytes of |clientDataJSON|. - : extensionOutputsMap - :: whose value is an [=ordered map=] with [=map/keys=] of type [=extension identifier=] - and [=map/values=] of type [=client extension output=]. - [=extensionOutputsMap=]'s [=map/entries=] are - created by running each extension's [=client extension processing=] algorithm to create the [=client - extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. + : extensionOutputsMap + :: whose value is an [=ordered map=] with [=map/keys=] of type [=extension identifier=] + and [=map/values=] of type [=client extension output=]. [=extensionOutputsMap=]'s + [=map/entries=] are created by running each extension's [=client extension processing=] algorithm to create + the [=client extension outputs=], for each [=client extension=] in + {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. - Issue: is there any special way to declare |credentialCreationData| such that it properly exists when - [=constructCredentialCallback=] (defined just below) is invoked? + Issue: is there any special way to declare |credentialCreationData| such that it properly exists when + [=constructCredentialCallback=] (defined just below) is invoked? - - 3. Let |value| be a [=struct=] whose [=item=] is: + 3. Let |value| be a [=struct=] whose [=item=] is: - : constructCredentialCallback - :: whose value is a Web IDL {{Function}} [=callback function type=] value implementing the - steps defined in [[#constructCredentialCallback]]. + : constructCredentialCallback + :: whose value is a Web IDL {{Function}} [=callback function type=] value implementing the + steps defined in [[#constructCredentialCallback]]. - 5. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on - |authenticator| and [=set/remove=] it from |issuedRequests|. + 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. + 6. Return |value| and terminate this algorithm.
    @@ -984,49 +984,51 @@ 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 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. -
    + : 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}}". @@ -1735,7 +1737,7 @@ input parameters: This sequence is ordered from most preferred to least preferred. The platform makes a best-effort to create the most preferred credential that it can. - An optional list of {{PublicKeyCredentialDescriptor}} objects provided by the [=[RP]=] with the intention that, if any of - these are known to the authenticator, it should not create a new credential. |excludeCredentialDescriptorList| contains a + these are known to the authenticator, it should not create a new credential. |excludeCredentialDescriptorList| contains a list of known credentials. - The |requireResidentKey| member of the |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}} dictionary. - The |requireUserVerification| member of the |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}} dictionary. @@ -2539,7 +2541,7 @@ the attestation=] is consistent with the fields of the attestation certificate's The authenticator produces |sig| by concatenating |authenticatorData| and |clientDataHash|, and signing the result using the credential private key. It sets |alg| to the algorithm of the signature format. - + : Verification procedure :: Verification is performed as follows: From 7b0d9a8366f5b94fe47895132abcd678b25f66cc Mon Sep 17 00:00:00 2001 From: JeffH Date: Tue, 3 Oct 2017 10:43:42 -0700 Subject: [PATCH 37/50] fix code tags placement --- index.bs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.bs b/index.bs index e9bbb1b97..ce02f735c 100644 --- a/index.bs +++ b/index.bs @@ -783,9 +783,9 @@ This algorithm accepts one argument: 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. + bytes of |credentialCreationData|.[=attestationObjectResult=]'s value. -3. Let |id| be |attestationObject|.authData.attestation data.credential ID (see [[#sec-attestation-data]] +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: @@ -798,16 +798,16 @@ When this method is invoked, the user agent MUST execute the following algorithm : {{AuthenticatorResponse/clientDataJSON}} :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of - |credentialCreationData|.[=clientDataJSONResult=]. + |credentialCreationData|.[=clientDataJSONResult=]. : {{AuthenticatorAttestationResponse/attestationObject}} :: |attestationObject| : {{PublicKeyCredential/clientExtensionResults}} :: A new {{AuthenticationExtensions}} object associated with |global| containing the bytes - of |credentialCreationData|.[=extensionOutputsMap=]'s value. + of |credentialCreationData|.[=extensionOutputsMap=]'s value. - Note: |credentialCreationData|.[=extensionOutputsMap=] is an [=ordered map=] whose [=map/keys=] are all + 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. From 81a8921e6114df8ba5d895a587ee04a45b988178 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 5 Oct 2017 15:51:59 -0700 Subject: [PATCH 38/50] correct bugs in prior merge conflict resolution, doh --- index.bs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 64b057e06..41d5e8a41 100644 --- a/index.bs +++ b/index.bs @@ -566,7 +566,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 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}} + or the {{PublicKeyCredentialUserEntity/id}} 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 @@ -1018,6 +1018,9 @@ When this method is invoked, the user agent MUST execute the following algorithm : {{AuthenticatorAssertionResponse/signature}} :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of the returned {{signature}}. + : {{AuthenticatorAssertionResponse/userId}} + :: A new {{DOMString}} containing the user handle returned from the successful + [=authenticatorGetAssertion=] operation, as defined in [[#op-get-assertion]]. : {{PublicKeyCredential/clientExtensionResults}} :: A new {{AuthenticationExtensions}} object containing the [=extension identifier=] → [=client extension From 7e06037efcd4d4e9a2ed608e440f45141c8b0099 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 6 Oct 2017 12:55:43 -0700 Subject: [PATCH 39/50] rm 'the bytes of' --- index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index 41d5e8a41..0ffcb7b0f 100644 --- a/index.bs +++ b/index.bs @@ -804,8 +804,8 @@ When this method is invoked, the user agent MUST execute the following algorithm :: |attestationObject| : {{PublicKeyCredential/clientExtensionResults}} - :: A new {{AuthenticationExtensions}} object associated with |global| containing the bytes - of |credentialCreationData|.[=extensionOutputsMap=]'s value. + :: A new {{AuthenticationExtensions}} object associated with |global| containing + |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 From 3d771c2629faee8429efdb7d1c6c04afb9cde064 Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 11 Oct 2017 08:24:51 -0700 Subject: [PATCH 40/50] add missing @@EDITOR-ANCHOR-01A --- index.bs | 1 + 1 file changed, 1 insertion(+) diff --git a/index.bs b/index.bs index 4129dc9f2..ec2aac9bf 100644 --- a/index.bs +++ b/index.bs @@ -699,6 +699,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. Invoke the [=authenticatorMakeCredential=] operation on |authenticator| with |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, From 622d11a860e28e456d9d09dd57465f1063fd058e Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 11 Oct 2017 12:02:20 -0700 Subject: [PATCH 41/50] auto-number some steps --- index.bs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/index.bs b/index.bs index ec2aac9bf..9a55dde7d 100644 --- a/index.bs +++ b/index.bs @@ -731,7 +731,7 @@ When this method is invoked, the user agent MUST execute the following algorithm : If any |authenticator| indicates success, :: 1. [=set/Remove=] |authenticator| from |issuedRequests|. - 2. Let |credentialCreationData| be a [=struct=] whose [=items=] are: + 1. Let |credentialCreationData| be a [=struct=] whose [=items=] are: : attestationObjectResult :: whose value is the bytes returned from the successful [=authenticatorMakeCredential=] operation. @@ -757,16 +757,16 @@ When this method is invoked, the user agent MUST execute the following algorithm type of {{Credential}}-derived object. --> - 3. Let |value| be a [=struct=] whose [=item=] is: + 1. Let |value| be a [=struct=] whose [=item=] is: : constructCredentialCallback :: whose value is a Web IDL {{Function}} [=callback function type=] value implementing the steps defined in [[#constructCredentialCallback]]. - 5. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on + 1. [=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 |value| and terminate this algorithm. @@ -793,10 +793,10 @@ 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. -3. Let |id| be |attestationObject|.authData.attestation data.credential ID (see [[#sec-attestation-data]] +1. 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: +1. Let |pubKeyCred| be a new {{PublicKeyCredential}} object associated with |global| whose fields are: : {{PublicKeyCredential/[[identifier]]}} :: |id| @@ -819,7 +819,7 @@ When this method is invoked, the user agent MUST execute the following algorithm 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|. +1. Return |pubKeyCred|. ### Use an existing credential to make an assertion - PublicKeyCredential's `[[DiscoverFromExternalSource]](options)` method ### {#getAssertion} From a8799aafa60c6b00d0264b99529e8682ea33a1a9 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 13 Oct 2017 15:34:44 -0700 Subject: [PATCH 42/50] re- fix #466 (due to merge-from-master), fix #536 --- index.bs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/index.bs b/index.bs index eed9338d9..544fe8db3 100644 --- a/index.bs +++ b/index.bs @@ -717,7 +717,8 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Invoke the [=authenticatorMakeCredential=] operation on |authenticator| with |clientDataHash|, |options|.{{MakePublicKeyCredentialOptions/rp}}, |options|.{{MakePublicKeyCredentialOptions/user}}, - |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/rk}}, + |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/requireResidentKey}}, + |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/requireUserVerification}}, |credTypesAndPubKeyAlgs|, |excludeCredentialDescriptorList|, and |authenticatorExtensions| as parameters. @@ -1797,14 +1798,16 @@ This operation must be invoked in an authenticator session which has no other op input parameters: -: |rpId| -:: The caller's [=RP ID=], as determined by the user agent and the client. : |hash| :: The [=hash of the serialized client data=], provided by the client. : |rpEntity| :: The [=[RP]=]'s {{PublicKeyCredentialRpEntity}}. : |userEntity| :: The user account's {{PublicKeyCredentialUserEntity}}, containing the [=user handle=] given by the [=[RP]=]. +: |requireResidentKey| +:: |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{requireResidentKey}}. +: |requireUserVerification| +:: |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{requireUserVerification}}. : |credTypesAndPubKeyAlgs| :: A sequence of pairs of {{PublicKeyCredentialType}} and public key algorithms ({{COSEAlgorithmIdentifier}}) requested by the [=[RP]=]. This sequence is ordered from most preferred to least preferred. The platform makes a best-effort to create the most @@ -1813,10 +1816,6 @@ input parameters: :: An optional list of {{PublicKeyCredentialDescriptor}} objects provided by the [=[RP]=] with the intention that, if any of these are known to the authenticator, it should not create a new credential. |excludeCredentialDescriptorList| contains a list of known credentials. -: |requireResidentKey| -:: |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{requireResidentKey}}. -: |requireUserVerification| -:: |options|.{{MakePublicKeyCredentialOptions/authenticatorSelection}}.{{requireUserVerification}} : |extensions| :: A [=map=] from [=extension identifiers=] to their [=authenticator extension inputs=], created by the client based on the extensions requested by the [=[RP]=], if any. From f5a08fbb77a25eb0a911ae35d1e24f25fd71a8f7 Mon Sep 17 00:00:00 2001 From: JeffH Date: Fri, 13 Oct 2017 16:31:32 -0700 Subject: [PATCH 43/50] eliminate callback and just return an algorithm from #createCredential --- index.bs | 91 +++++++++++++++++++++----------------------------------- 1 file changed, 34 insertions(+), 57 deletions(-) diff --git a/index.bs b/index.bs index 544fe8db3..6e9633148 100644 --- a/index.bs +++ b/index.bs @@ -763,78 +763,55 @@ When this method is invoked, the user agent MUST execute the following algorithm the [=client extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. - Issue: is there any special way to declare |credentialCreationData| such that it properly exists when - [=constructCredentialCallback=] (defined just below) is invoked? + 1. Let |constructCredentialAlg| be an algorithm that takes a [=environment settings object/global object=] + |global|, and whose steps are: - - - 1. Let |value| be a [=struct=] whose [=item=] is: - - : constructCredentialCallback - :: whose value is a Web IDL {{Function}} [=callback function type=] value implementing the - steps defined in [[#constructCredentialCallback]]. - - 1. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on - |authenticator| and [=set/remove=] it from |issuedRequests|. - - 1. Return |value| and terminate this algorithm. + 1. Let |attestationObject| be a new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the + bytes of |credentialCreationData|.[=attestationObjectResult=]'s value. - - -1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". - -During the above process, the user agent SHOULD show some UI to the user to guide them in the process of selecting and -authorizing an authenticator. - + 1. Let |id| be |attestationObject|.authData.attestation data.credential ID (see [[#sec-attestation-data]] + and [[#sec-authenticator-data]]). + 1. Let |pubKeyCred| be a new {{PublicKeyCredential}} object associated with |global| whose fields are: -#### Construct the credential - `constructCredentialCallback` method #### {#constructCredentialCallback} - -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]]. + : {{PublicKeyCredential/[[identifier]]}} + :: |id| -This algorithm accepts one argument: + : {{PublicKeyCredential/response}} + :: A new {{AuthenticatorAttestationResponse}} object associated with |global| whose fields are: - : |global| - :: Which must be its caller's [=current settings object=]'s [=environment settings object/global object=]. + : {{AuthenticatorResponse/clientDataJSON}} + :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of + |credentialCreationData|.[=clientDataJSONResult=]. -When this method is invoked, the user agent MUST execute the following algorithm: + : {{AuthenticatorAttestationResponse/attestationObject}} + :: |attestationObject| -1. Let |attestationObject| be a new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the - bytes of |credentialCreationData|.[=attestationObjectResult=]'s value. - -1. Let |id| be |attestationObject|.authData.attestation data.credential ID (see [[#sec-attestation-data]] - and [[#sec-authenticator-data]]). + : {{PublicKeyCredential/clientExtensionResults}} + :: A new {{AuthenticationExtensions}} object associated with |global| containing + |credentialCreationData|.[=extensionOutputsMap=]'s value. -1. Let |pubKeyCred| be a new {{PublicKeyCredential}} object associated with |global| whose fields are: + 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. - : {{PublicKeyCredential/[[identifier]]}} - :: |id| + 1. Return |pubKeyCred|. - : {{PublicKeyCredential/response}} - :: A new {{AuthenticatorAttestationResponse}} object associated with |global| whose fields are: + 1. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on + |authenticator| and [=set/remove=] it from |issuedRequests|. - : {{AuthenticatorResponse/clientDataJSON}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of - |credentialCreationData|.[=clientDataJSONResult=]. + 1. Return |constructCredentialAlg| and terminate this algorithm. - : {{AuthenticatorAttestationResponse/attestationObject}} - :: |attestationObject| + Issue: Do we need to replicitly return both |constructCredentialAlg| and |credentialCreationData| here? - : {{PublicKeyCredential/clientExtensionResults}} - :: A new {{AuthenticationExtensions}} object associated with |global| containing - |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. +1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". -1. Return |pubKeyCred|. +During the above process, the user agent SHOULD show some UI to the user to guide them in the process of selecting and +authorizing an authenticator. + ### Use an existing credential to make an assertion ### {#getAssertion} @@ -1050,7 +1027,7 @@ method is invoked, the user agent MUST: [[#op-get-assertion]]. : {{PublicKeyCredential/clientExtensionResults}} - :: A new {{AuthenticationExtensions}} object containing the + :: 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. From 3d84d14b436635d1774f7be5b033b83e2b9e0d5f Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 18 Oct 2017 11:45:50 -0700 Subject: [PATCH 44/50] continue fix conflicts from merge from master --- index.bs | 97 -------------------------------------------------------- 1 file changed, 97 deletions(-) diff --git a/index.bs b/index.bs index 11f4320cc..4c9ba9c72 100644 --- a/index.bs +++ b/index.bs @@ -731,7 +731,6 @@ When this method is invoked, the user agent MUST execute the following algorithm and responses from the authenticators:
    -<<<<<<< HEAD : If the |adjustedTimeout| timer expires, :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. @@ -978,7 +977,6 @@ method is invoked, the user agent MUST:
    -<<<<<<< HEAD : If the |adjustedTimeout| timer expires, :: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. @@ -1018,105 +1016,10 @@ method is invoked, the user agent MUST: returned from the successful [=authenticatorGetAssertion=] operation, as defined in [[#op-get-assertion]]. - : {{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.
    -||||||| merged common ancestors -
    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]]}} - :: 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]]. - : {{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}} - : {{AuthenticatorAssertionResponse/userHandle}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the [=user handle=] returned from the successful [=authenticatorGetAssertion=] - operation, as defined in [[#op-get-assertion]]. - : {{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]]}} - :: 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]]. - : {{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}} - : {{AuthenticatorAssertionResponse/userHandle}} - :: A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the [=user handle=] returned from the successful [=authenticatorGetAssertion=] - operation, as defined in [[#op-get-assertion]]. - - 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. -
    - ->>>>>>> master 1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". From 9d1db3aa47a19edc8cd31e464687fa13e47694d7 Mon Sep 17 00:00:00 2001 From: JeffH Date: Wed, 18 Oct 2017 12:57:32 -0700 Subject: [PATCH 45/50] fix a couple of issue #466 stragglers in #op-make-cred --- index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index 4c9ba9c72..427ffa7d6 100644 --- a/index.bs +++ b/index.bs @@ -1817,8 +1817,8 @@ When this operation is invoked, the authenticator must perform the following pro 1. Let |credentialId| be a new identifier for this credential that is globally unique with high probability across all credentials with the same type across all authenticators. 1. Let |userHandle| be |userEntity|.{{PublicKeyCredentialUserEntity/id}}. - 1. Associate the |credentialId| and |privateKey| with |rpId| and |userHandle|. - 1. Delete any older credentials with the same |rpId| and |userHandle| that are stored locally by the [=authenticator=]. + 1. Associate the |credentialId| and |privateKey| with |rpEntity.id| and |userHandle|. + 1. Delete any older credentials with the same |rpEntity.id| and |userHandle| that are stored locally by the [=authenticator=]. 1. If any error occurred while creating the new credential object, return an error code equivalent to "{{UnknownError}}" and terminate the operation. 1. Let |processedExtensions| be the result of [=authenticator extension processing=] for each supported [=extension identifier=]/input From 7e035e91d18f0d7555074f77d06b84a09221e5fb Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 19 Oct 2017 10:44:08 -0700 Subject: [PATCH 46/50] revert to prior AuthenticationExtensions language per jyasskin --- index.bs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/index.bs b/index.bs index 427ffa7d6..b91d25431 100644 --- a/index.bs +++ b/index.bs @@ -756,12 +756,11 @@ When this method is invoked, the user agent MUST execute the following algorithm : clientDataJSONResult :: whose value is the bytes of |clientDataJSON|. - : extensionOutputsMap - :: whose value is an [=ordered map=] with [=map/keys=] of type [=extension identifier=] - and [=map/values=] of type [=client extension output=]. [=extensionOutputsMap=]'s - [=map/entries=] are created by running each extension's [=client extension processing=] algorithm to create - the [=client extension outputs=], for each [=client extension=] in - {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. + : clientExtensionResults + :: whose value is an {{AuthenticationExtensions}} object containing [=extension identifier=] → + [=client extension output=] entries. The entries are created by running each extension's + [=client extension processing=] algorithm to create the [=client extension outputs=], for each + [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. 1. Let |constructCredentialAlg| be an algorithm that takes a [=environment settings object/global object=] |global|, and whose steps are: From dbee09212b06495a16b0e72171154814cd07daf7 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 19 Oct 2017 10:59:12 -0700 Subject: [PATCH 47/50] add inline spec issue pointing to issue #657 --- index.bs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.bs b/index.bs index b91d25431..49217a27a 100644 --- a/index.bs +++ b/index.bs @@ -785,6 +785,10 @@ When this method is invoked, the user agent MUST execute the following algorithm : {{AuthenticatorAttestationResponse/attestationObject}} :: |attestationObject| + Issue: need to place [=clientExtensionResults=] somewhere such that the data is subsequently available + to RP script when the latter invokes `PublicKeyCredential.getClientExtensionResults()`. + See [issue #657](https://github.com/w3c/webauthn/issues/657). + 1. Return |pubKeyCred|. 1. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on From 942e7b4fcd766451298febdce38b5fdea700a562 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 19 Oct 2017 11:33:52 -0700 Subject: [PATCH 48/50] minor cleanups, remove issue wrt not explicitly returning |credentialCreationData| --- index.bs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index 49217a27a..17fc10626 100644 --- a/index.bs +++ b/index.bs @@ -762,7 +762,7 @@ When this method is invoked, the user agent MUST execute the following algorithm [=client extension processing=] algorithm to create the [=client extension outputs=], for each [=client extension=] in {{AuthenticatorResponse/clientDataJSON}}.clientExtensions. - 1. Let |constructCredentialAlg| be an algorithm that takes a [=environment settings object/global object=] + 1. Let |constructCredentialAlg| be an algorithm that takes a [=global object=] |global|, and whose steps are: 1. Let |attestationObject| be a new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the @@ -785,7 +785,7 @@ When this method is invoked, the user agent MUST execute the following algorithm : {{AuthenticatorAttestationResponse/attestationObject}} :: |attestationObject| - Issue: need to place [=clientExtensionResults=] somewhere such that the data is subsequently available + Issue: need to place [=clientExtensionResults=] data somewhere such that the data is subsequently available to RP script when the latter invokes `PublicKeyCredential.getClientExtensionResults()`. See [issue #657](https://github.com/w3c/webauthn/issues/657). @@ -796,8 +796,6 @@ When this method is invoked, the user agent MUST execute the following algorithm 1. Return |constructCredentialAlg| and terminate this algorithm. - Issue: Do we need to replicitly return both |constructCredentialAlg| and |credentialCreationData| here? - 1. Return a {{DOMException}} whose name is "{{NotAllowedError}}". From 32e2eb6e362774f4ba2138fce8c7db343b0cf2b3 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 19 Oct 2017 11:36:12 -0700 Subject: [PATCH 49/50] fix annoying bikeshed warning wrt 'rpEntity' --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 17fc10626..5bcac27fd 100644 --- a/index.bs +++ b/index.bs @@ -1775,7 +1775,7 @@ input parameters: : |hash| :: The [=hash of the serialized client data=], provided by the client. -: |rpEntity| +: rpEntity :: The [=[RP]=]'s {{PublicKeyCredentialRpEntity}}. : |userEntity| :: The user account's {{PublicKeyCredentialUserEntity}}, containing the [=user handle=] given by the [=[RP]=]. From 4b2193e02fc48cdc6b4f3793aabe0e246490d7b1 Mon Sep 17 00:00:00 2001 From: JeffH Date: Thu, 19 Oct 2017 11:45:11 -0700 Subject: [PATCH 50/50] correctly fix warning as well as other incorrect markup --- index.bs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.bs b/index.bs index 5bcac27fd..41b360afa 100644 --- a/index.bs +++ b/index.bs @@ -1775,7 +1775,7 @@ input parameters: : |hash| :: The [=hash of the serialized client data=], provided by the client. -: rpEntity +: |rpEntity| :: The [=[RP]=]'s {{PublicKeyCredentialRpEntity}}. : |userEntity| :: The user account's {{PublicKeyCredentialUserEntity}}, containing the [=user handle=] given by the [=[RP]=]. @@ -1818,8 +1818,8 @@ When this operation is invoked, the authenticator must perform the following pro 1. Let |credentialId| be a new identifier for this credential that is globally unique with high probability across all credentials with the same type across all authenticators. 1. Let |userHandle| be |userEntity|.{{PublicKeyCredentialUserEntity/id}}. - 1. Associate the |credentialId| and |privateKey| with |rpEntity.id| and |userHandle|. - 1. Delete any older credentials with the same |rpEntity.id| and |userHandle| that are stored locally by the [=authenticator=]. + 1. Associate the |credentialId| and |privateKey| with |rpEntity|.{{PublicKeyCredentialRpEntity/id}} and |userHandle|. + 1. Delete any older credentials with the same |rpEntity|.{{PublicKeyCredentialRpEntity/id}} and |userHandle| that are stored locally by the [=authenticator=]. 1. If any error occurred while creating the new credential object, return an error code equivalent to "{{UnknownError}}" and terminate the operation. 1. Let |processedExtensions| be the result of [=authenticator extension processing=] for each supported [=extension identifier=]/input