From f63a368a9059fba761cdef0565bb99b7a94255e8 Mon Sep 17 00:00:00 2001 From: "J.C. Jones" Date: Wed, 22 Feb 2017 13:17:22 -0700 Subject: [PATCH] Bug #256 - Change "relaxing" of RP to the HTML "registrable suffix" algorithm - Rebased on top of PR 336's linking changes - Updates from review by jyasskin and equalsJeffH - Catches a couple extra un-linked DOMExceptions - Refers to the new "is a registrable domain suffix of or is equal to" algorithm in WHATWG HTML [1] - Note, there is still a linking error after a bikeshed update, but I'm guessing that change is so new that's not in the bikeshed metadata yet, so I'm going to leave it for now and hope it fixes itself. [1] https://html.spec.whatwg.org/multipage/browsers.html#is-a-registrable-domain-suffix-of-or-is-equal-to --- index.bs | 81 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/index.bs b/index.bs index 736ba356d..32ae722f6 100644 --- a/index.bs +++ b/index.bs @@ -47,7 +47,6 @@ spec: HTML52; urlPrefix: https://w3c.github.io/html/ text: origin; url: concept-cross-origin text: opaque origin; url: opaque-origin text: tuple origin - text: relaxing the same-origin restriction urlPrefix: webappapis.html type: dfn text: current settings object; url:current-settings-object @@ -181,7 +180,7 @@ This specification relies on several other underlying specifications. : HTML :: The concepts of current settings object, origin, - opaque origin, relaxing the same-origin restriction, and the {{Navigator}} interface are + opaque origin, is a registrable domain suffix of or is equal to, and the {{Navigator}} interface are defined in [[!HTML52]]. : Web Cryptography API @@ -406,22 +405,26 @@ When this method is invoked, the user agent MUST execute the following algorithm value. If {{ScopedCredentialOptions/timeout}} was not specified, then set |adjustedTimeout| to a platform-specific default. -2. Let |promise| be [=a new Promise=]. Return |promise| and start a timer for |adjustedTimeout| milliseconds. +1. Let |promise| be [=a new Promise=]. Return |promise| and start a timer for |adjustedTimeout| milliseconds. Then asynchronously continue executing the following steps. If any fatal error is encountered in this process other than the - ones enumerated below, cancel the timer, reject |promise| with a DOMException whose name is "{{UnknownError}}", and terminate + ones enumerated below, cancel the timer, reject |promise| with a {{DOMException}} whose name is "{{UnknownError}}", and terminate this algorithm. -3. Set |callerOrigin| to the current settings object's origin. If |callerOrigin| is +1. Set |callerOrigin| to the current settings object's origin. If |callerOrigin| is an opaque origin, reject |promise| with a {{DOMException}} whose name is "{{NotAllowedError}}", and - terminate this algorithm. Otherwise, - - If the {{ScopedCredentialOptions/rpId}} member of {{options}} is not present, then set |rpId| to |callerOrigin|. - - If the {{ScopedCredentialOptions/rpId}} member of {{options}} is present, then invoke the procedure used for - relaxing the same-origin restriction by setting the `document.domain` attribute, using - {{ScopedCredentialOptions/rpId}} as the given value but without changing the current document's `domain`. If no errors - are thrown, set |rpId| to the value of `host` as computed by this procedure. Otherwise, reject |promise| with a - {{DOMException}} whose name is "{{SecurityError}}", and terminate this algorithm. - -4. Process each element of {{cryptoParameters}} using the following steps, to produce a new sequence |normalizedParameters|. + terminate this algorithm. + +1. If the {{ScopedCredentialOptions/rpId}} member of {{options}} is not present, then set |rpId| to + |callerOrigin|. Otherwise, + - Let |effectiveDomain| be the |callerOrigin|'s effective domain. + - If |effectiveDomain| is null, then reject |promise| with a {{DOMException}} whose name is "{{SecurityError}}" + and terminate this algorithm. + - If {{ScopedCredentialOptions/rpId}} is not a registrable domain suffix of and is not equal to + |effectiveDomain|, reject |promise| with a {{DOMException}} whose name is "{{SecurityError}}", and + terminate this algorithm. + - Set |rpId| to the {{ScopedCredentialOptions/rpId}}. + +1. Process each element of {{cryptoParameters}} using the following steps, to produce a new sequence |normalizedParameters|. - Let |current| be the currently selected element of {{cryptoParameters}}. - If `current.type` does not contain a {{ScopedCredentialType}} supported by this implementation, then stop processing |current| and move on to the next element in {{cryptoParameters}}. @@ -431,32 +434,32 @@ When this method is invoked, the user agent MUST execute the following algorithm - Add a new object of type {{ScopedCredentialParameters}} to |normalizedParameters|, with |type| set to `current.type` and |algorithm| set to |normalizedAlgorithm|. -5. If |normalizedAlgorithm| is empty and {{cryptoParameters}} was not empty, cancel the timer started in step 2, reject +1. If |normalizedAlgorithm| is empty and {{cryptoParameters}} was not empty, cancel the timer started in step 2, reject |promise| with a DOMException whose name is "{{NotSupportedError}}", and terminate this algorithm. -6. If the {{ScopedCredentialOptions/extensions}} member of {{options}} is present, process any extensions supported by +1. If the {{ScopedCredentialOptions/extensions}} member of {{options}} is present, process any extensions supported by this client platform, to produce the extension data that needs to be sent to the authenticator. If an error is encountered while processing an extension, skip that extension and do not produce any extension data for it. Call the result of this processing |clientExtensions|. -7. Use {{attestationChallenge}}, |callerOrigin| and |rpId|, along with the token binding key associated with |callerOrigin| (if +1. Use {{attestationChallenge}}, |callerOrigin| and |rpId|, along with the token binding key associated with |callerOrigin| (if any), to create a {{ClientData}} structure representing this request. Choose a hash algorithm for {{ClientData/hashAlg}} and compute the {{ScopedCredentialInfo/clientDataJSON}} and its clientDataHash. -8. Initialize |issuedRequests| and |currentlyAvailableAuthenticators| to empty lists. +1. Initialize |issuedRequests| and |currentlyAvailableAuthenticators| to empty lists. -9. For each authenticator currently available on this platform, add the authenticator to |currentlyAvailableAuthenticators| +1. For each authenticator currently available on this platform, add the authenticator to |currentlyAvailableAuthenticators| unless the {{ScopedCredentialOptions/attachment}} member of {{options}} is present. In that case, let |attachment| be {{ScopedCredentialOptions/attachment}}, and add the authenticator to |currentlyAvailableAuthenticators| if its attachment modality matches |attachment|. -10. For each authenticator in |currentlyAvailableAuthenticators|: asynchronously invoke the authenticatorMakeCredential +1. For each authenticator in |currentlyAvailableAuthenticators|: asynchronously invoke the authenticatorMakeCredential operation on that authenticator with |rpId|, clientDataHash, {{accountInformation}}, |normalizedParameters|, {{ScopedCredentialOptions/excludeList}} and |clientExtensions| as parameters. Add a corresponding entry to |issuedRequests|. - For each credential |C| in the {{ScopedCredentialOptions/excludeList}} member of {{options}} that has a non-empty |transports| list, optionally use only the specified transports to test for the existence of |C|. -11. While |issuedRequests| is not empty, perform the following actions depending upon the |adjustedTimeout| timer and responses +1. While |issuedRequests| is not empty, perform the following actions depending upon the |adjustedTimeout| timer and responses from the authenticators: - If the |adjustedTimeout| timer expires, then for each entry in |issuedRequests| invoke the authenticatorCancel operation on that authenticator and remove its entry from the list. @@ -472,7 +475,7 @@ When this method is invoked, the user agent MUST execute the following algorithm remove its entry from the list. - Resolve |promise| with |value| and terminate this algorithm. -12. Reject |promise| with a {{DOMException}} whose name is "{{NotAllowedError}}", and terminate this algorithm. +1. Reject |promise| with a {{DOMException}} whose name is "{{NotAllowedError}}", and terminate this algorithm. 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. @@ -504,33 +507,37 @@ When this method is invoked, the user agent MUST execute the following algorithm platform and if not, correct it to the closest value lying within that range. Set |adjustedTimeout| to this adjusted value. If {{AssertionOptions/timeout}} was not specified, then set |adjustedTimeout| to a platform-specific default. -2. Let |promise| be [=a new Promise=]. Return |promise| and start a timer for |adjustedTimeout| milliseconds. +1. Let |promise| be [=a new Promise=]. Return |promise| and start a timer for |adjustedTimeout| milliseconds. Then asynchronously continue executing the following steps. If any fatal error is encountered in this process other than the - ones enumerated below, cancel the timer, reject |promise| with a DOMException whose name is "{{UnknownError}}", and terminate + ones enumerated below, cancel the timer, reject |promise| with a {{DOMException}} whose name is "{{UnknownError}}", and terminate this algorithm. -3. Set |callerOrigin| to the current settings object's origin. If |callerOrigin| is +1. Set |callerOrigin| to the current settings object's origin. If |callerOrigin| is an opaque origin, reject |promise| with a {{DOMException}} whose name is "{{NotAllowedError}}", and - terminate this algorithm. Otherwise, - - If the {{AssertionOptions/rpId}} member of {{options}} is not present, then set |rpId| to |callerOrigin|. - - If the {{AssertionOptions/rpId}} member of {{options}} is present, then invoke the procedure used for relaxing - the same-origin restriction by setting the `document.domain` attribute, using {{AssertionOptions/rpId}} as the given - value but without changing the current document's `domain`. If no errors are thrown, set |rpId| to the value of `host` - as computed by this procedure. Otherwise, reject |promise| with a {{DOMException}} whose name is "{{SecurityError}}", and + terminate this algorithm. + +1. If the {{ScopedCredentialOptions/rpId}} member of {{options}} is not present, then set |rpId| to + |callerOrigin|. Otherwise, + - Let |effectiveDomain| be the |callerOrigin|'s effective domain. + - If |effectiveDomain| is null, then reject |promise| with a {{DOMException}} whose name is "{{SecurityError}}" + and terminate this algorithm. + - If {{ScopedCredentialOptions/rpId}} is not a registrable domain suffix of and is not equal to + |effectiveDomain|, reject |promise| with a {{DOMException}} whose name is "{{SecurityError}}", and terminate this algorithm. + - Set |rpId| to the {{ScopedCredentialOptions/rpId}}. -4. If the {{AssertionOptions/extensions}} member of {{options}} is present, process any extensions supported by this +1. If the {{AssertionOptions/extensions}} member of {{options}} is present, process any extensions supported by this client platform, to produce the extension data that needs to be sent to the authenticator. If an error is encountered while processing an extension, skip that extension and do not produce any extension data for it. Call the result of this processing |clientExtensions|. -5. Use {{assertionChallenge}}, |callerOrigin| and |rpId|, along with the token binding key associated with |callerOrigin| (if +1. Use {{assertionChallenge}}, |callerOrigin| and |rpId|, along with the token binding key associated with |callerOrigin| (if any), to create a {{ClientData}} structure representing this request. Choose a hash algorithm for {{ClientData/hashAlg}} and compute the {{AuthenticationAssertion/clientDataJSON}} and clientDataHash. -6. Initialize |issuedRequests| to an empty list. +1. Initialize |issuedRequests| to an empty list. -7. For each authenticator currently available on this platform, perform the following steps: +1. For each authenticator currently available on this platform, perform the following steps: - If the {{AssertionOptions/allowList}} member of {{options}} is empty, let |credentialList| be an empty list. Otherwise, execute a platform-specific procedure to determine which, if any, credentials listed in {{AssertionOptions/allowList}} might be present on this authenticator, and set |credentialList| to this filtered list. If no such filtering is @@ -544,7 +551,7 @@ When this method is invoked, the user agent MUST execute the following algorithm clientDataHash, |credentialList|, and |clientExtensions| as parameters. - Add an entry to |issuedRequests|, corresponding to this request. -8. While |issuedRequests| is not empty, perform the following actions depending upon the |adjustedTimeout| timer and responses +1. While |issuedRequests| is not empty, perform the following actions depending upon the |adjustedTimeout| timer and responses from the authenticators: - If the timer for |adjustedTimeout| expires, then for each entry in |issuedRequests| invoke the authenticatorCancel operation on that authenticator and remove its entry from the list. @@ -560,7 +567,7 @@ When this method is invoked, the user agent MUST execute the following algorithm remove its entry from the list. - Resolve |promise| with |value| and terminate this algorithm. -9. Reject |promise| with a {{DOMException}} whose name is "{{NotAllowedError}}", and terminate this algorithm. +1. Reject |promise| with a {{DOMException}} whose name is "{{NotAllowedError}}", and terminate this algorithm. 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 with which to complete the operation.