- From: Kari Hurtta <hurtta-ietf@elmme-mailer.org>
- Date: Sat, 27 Apr 2019 19:14:52 +0300 (EEST)
- To: HTTP Working Group <ietf-http-wg@w3.org>
- CC: HTTP Working Group <ietf-http-wg@w3.org>, Mike West <mkwst@google.com>, Ilari Liusvaara <ilariliusvaara@welho.com>, Kari Hurtta <hurtta-ietf@elmme-mailer.org>
HTTP State Tokens https://tools.ietf.org/html/draft-west-http-state-tokens-00 For Server opt-in (or opt-out) on ( <20190403182945.069B4C3F26@welho-filter2.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0007.html ) I used delivery=void and same value on "delivery" metadata on HTTP State Token. This not work well on subresources which need user opt in / opt out. User opt in / out questions are practical to query from origin of top browser content. Origins which serve for example images are bad position to ask from user. http://ec.europa.eu/ipg/basics/legal/cookies/index_en.htm If HTTP State Token is "used for the sole purpose of carrying out the transmission of a communication, and strictly necessary in order for the provider of an information society service explicitly required by the user to provide that service" then user opt in is not needed. So authentication, session-id, load-balancing for example does not need user consent. In that case origin can (and should) confirm HTTP State Token without prompt from user. When origin is used for resources and not top level document, it need delegate opt-in / opt-out to top level origin if user consent is needed. The "delivery" metadata of HTTP State Token can not used for mark that "delegate to top" because origin needs store real "delivery" option to it. This solution uses "confirm" metadata of HTTP State Token for origin opt-in / opt-out / delegate to top. I call that top level origin for that purpose as "confirm-top-origin". SameSite cookies ( https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.2.1 5.2.1. Document-based requests ) use more complex definition for top level origin. This needs more consideration. Also now Worker-driven requests probably gets "confirm-top-origin" as null. This is probably OK for this purpose. Also SameSite's "site for cookies" algorithm quits when some ancestor browsing contexts have different registered domain. That is not usable when determining top level origin for confirm=top. There is no "delivery=void" as there was on my mail "Server/Site opt-in" ( <20190403182945.069B4C3F26@welho-filter2.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0007.html ) instead "confirm=block" is used for that purpose. There is "Sec-Http-State:" dictionary member, whose key is "token", have value which is either byte sequence (sh-binary) or token (sh-token). That "token" with value type sh-token is also used on delivery related solutions "delivery=same-origin" ( <20190410165945.583F545C5D@welho-filter4.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0026.html ) and "cross-site" ( <20190414101536.3A23E45C0E@welho-filter4.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0037.html ) Another HTTP State Token metadata is used on top level origin to track opt-in for origins, which use confirm=top. Metadata "deliver-origins" is list of origins for which are allowed to use request Sec-Http-State: token=*value* when confirm=top for that origin and delivery -value allows giving of token value. Sec-Http-State: token=query indicates either that value for "confirm" is needed or that value for "delivery" is needed per "delivery=same-origin" ( <20190410165945.583F545C5D@welho-filter4.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0026.html ) and "cross-site" ( <20190414101536.3A23E45C0E@welho-filter4.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0037.html ). Sec-Http-State: token=void indicates either that value of "confirm" or that value of "delivery" blocks producing Sec-Http-State: token=*value* To resolve that, dictionary of Sec-Http-State may contain member whose key is "reason". This have values reason=delivery Value for "delivery" is required or "delivery" blocks token. reason=confirm Value for "confirm" is required or "confirm" blocks token. reason=top There is confirm=top but HTTP State Token for top level origin does not list current origin on "deliver-origins" metadata. reason=no-top There is confirm=top but top level origin is not available. reason=delivery/confirm Values for "delivery" and "confirm" are required. Dictionary of Sec-Http-State-Options may contain member whose key is "confirm" and whose value is one of "block", "deliver", or "top". Value "block" for "confirm" indicates that Sec-Http-State: token=void; reason=confirm is sent instead of Sec-Http-State: token=*value* ( assuming that "delivery" allows producing token=*value* ). Value "deliver" for "confirm" causes that Sec-Http-State: token=*value* is sent ( assuming that "delivery" allows producing token=*value* ). Value "top" for "confirm" indicates that either Sec-Http-State: token=void; reason=top or Sec-Http-State: token=*value* is produced ( assuming that "delivery" allows producing token=*value* ). If "delivery" indicates that token=query or token=void should be produced, that is used even when "confirm" indicates another value. On that case reason=delivery is used if "confirm" disagrees. However Sec-Http-State: token=void; reason=delivery/top is not used. When "delivery" causes token=void generated, value of "confirm" is not consulted. That causes Sec-Http-State: token=void; reason=delivery to be generated. This solution extends my "delivery=same-origin" suggestion ( <20190410165945.583F545C5D@welho-filter4.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0026.html ) and my "cross-site" suggestion ( <20190414101536.3A23E45C0E@welho-filter4.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0037.html ). Changes mentioned on my "delivery=same-origin" and "cross-site" suggestions should also be assumed. This solution does not be practical when HTTP State Token is used several places: o On load balancer on TLS terminator. That usage does not require user consent, o And same time on back end servers on way, which requires user's consent. Specially that breaks when user does not consent usage on back end servers. I guess that on that situation load balancer needs use Cookie instead. That then breaks when user is configured browser to ignore cookies and allow HTTP State Tokens only. ( But if backend server do not have state, it does not matter lot which server is selected on load balancing. So that breakage probably does not matter.) This solution includes also delivery=none for origins which want minimize request size (delivery=none is not state for user opt out). ( <20190328190729.F36474EEEA@welho-filter4.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019JanMar/0251.html ) On another mail I suggested to replace "same-site" with "same-domain". I mark this now as "same-site" [or "same-domain"]. ( <20190407171006.AD9EEB38@welho-filter3.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0013.html ) SameSite's "site for cookies" algorithm looks all ancestor browsing contexts and quits when some ancestor browsing contexts have different registered domain. It just not look "request-origin" and "target-origin". So I think that delivery should use delivery=same-domain instead. And Sec-Http-State-Options have also same-site=?0 or same-site=?1 And that "same-site" looks ancestor browser contents and sandboxed origin browsing context flag as SameSite looks. That makes difference also on delivery=same-origin situations. But that is not part of this Server/Site opt-in solution. On my previous "Server/Site opt-in" suggestion ( <20190403182945.069B4C3F26@welho-filter2.welho.com> https://lists.w3.org/Archives/Public/ietf-http-wg/2019AprJun/0007.html ) I wrote > If HTTP State Token's "delivery" property have value "query", > there need also method for Javascript to set that > to other value. This allows site/server use Javascript based consent > from user. On this suggestion Javascript does not have access to HTTP State Token's "delivery" property, but Javascipt have read/write access to "confirm" and "deliver-origins" properties of HTTP State Token. Third new HTTP State Token metadata is "query-origins", which Javascipt have read access. Metadata "query-origins" is list. When confirm=top is seen on Sec-Http-State-Options, response origin is added to "query-origins" metadata on top level origin's HTTP State Token. There was algorithm NotifyHostHTTPStateReset() which is called for origin when origin's HTTP State Token is generated. Similarly there also can be algorithm NotifyHostHTTPStateQuery() which is called with top level origin and response origin. This NotifyHostHTTPStateQuery() is called when new origin is added to "query-origins" metadata on top level origin's HTTP State Token. This may execute Javascript on content of top level origin (on content of top level document) with added response origin's name as argument. This allows producing implementing user opt in / out from Javascript. To avoid initial Sec-HTTP-State: token=query; reason=delivery/top request header filled, "delivery", "confirm" and "deliver-origins" values for origin need to be cached separately from Token Storage and with longer cache time than 1 hour (for example 50 hours). That may be then used when HTTP State Token is generated for origin. However I do NOT now include these changes. Changes are: 3.1. HTTP State Tokens https://tools.ietf.org/html/draft-west-http-state-tokens-00#section-3.1 | o "delivery" specifies the initiating contexts from which the token | can be delivered. It is an enum of either "same-origin", "same- | site", or "cross-site". Unless otherwise specified, its value is | "same-site". ⇒ ---- o "delivery" specifies the initiating contexts from which the token can be delivered. It is an enum of either "query", "none", "same-origin", "same-site" [or "same-domain"], or "cross-site". Unless otherwise specified, its value is "query". ---- Addition: ⇒ ---- o "confirm" specifies server or user opt-in/opt-out. It is an enum of either "query", "block", "deliver", or "top". Unless otherwise specified, its value is "query". User agent MAY allow to configure default value of "confirm" to either "query", "block" or "deliver". For example command line HTTP client may provide command option for specify default value of "confirm". o "deliver-origins" is list of origins in which token for that origin can be delivered if "confirm" metadata for that origin specifies "top". o "query-origins" is list of origins , whose "confirm" metadata specifies "top". Note: Both "delivery" and "confirm" needs initial value "query" because it is unlikely that origin can set them same time when user consent is required. [TBD: "query-origins" is lost when token is expired. ] [TBD: If user agent implements Javascript, that should be have read/write access to "confirm" and "deliver-origins" properties of HTTP State Token on correspond origin. ] [TBD: Some HTTP clients (for example data mining tools) may not instantiate browsing contexts. On these default value for "confirm" may need to be configured to other value than "query". ] ---- 3.3.1. Generate an HTTP State Token for an origin https://tools.ietf.org/html/draft-west-http-state-tokens-00#section-3.3.1 | 2. Let "token" be a newly created HTTP State Token with its | properties set as follows: | | * "creation": The current time. | | * "delivery": "same-site" ⇒ ---- 2. Let "token" be a newly created HTTP State Token with its properties set as follows: * "creation": The current time. * "delivery": "query" ---- Addition: ⇒ ---- * "confirm": "query" * "deliver-origins": empty list * "query-origins": empty list ---- [ TBD: Should "query-origins" to be recalculated on reset? This means walking all browsing context which origin is same than HTTP State Token's origin and then look all child browsing content and HTTP State Tokens for them for "confirm"'s value "top". ] 4.1. The 'Sec-Http-State' HTTP Header Field https://tools.ietf.org/html/draft-west-http-state-tokens-00#section-4.1 | o Exactly one member whose key is "token", and whose value is binary | content ([I-D.ietf-httpbis-header-structure], Section 3.9) that | encodes the HTTP state token's value for the origin to which the | header is delivered. | | If the "token" member contains more than 256 bits of binary | content, the member MUST be ignored. ⇒ ---- o Exactly one member whose key is "token", and whose value is either a byte sequence (sh-binary, [draft-ietf-httpbis-header-structure-10], Section 3.10) or a token (sh-token, [draft-ietf-httpbis-header-structure-10], Section 3.9). The byte sequence encodes the HTTP state token's value for the origin to which the header is delivered. This is a binary content. If the "token" member (as sh-binary) contains more than 256 bits of binary content, the member MUST be ignored. The token value (as sh-token) is "query" or "void". Value "query" indicates that HTTP client supports HTTP state tokens, but needs value for "delivery" or "confirm". Value "void" indicates that HTTP client supports HTTP state tokens, but "delivery" or "confirm" does not allow returning of a byte sequence. ---- | The dictionary MAY contain: Addition: ⇒ ---- o Exactly one member whose key is "reason", and whose value is one of the following tokens (sh-token, [draft-ietf-httpbis-header-structure-10], Section 3.9): "delivery", "confirm", "top", "no-top", or "delivery/confirm". ------ 4.2. The 'Sec-Http-State-Options' HTTP Header Field https://tools.ietf.org/html/draft-west-http-state-tokens-00#section-4.2 | The dictionary MAY contain: and there | o Exactly one member whose key is "delivery", and whose value is one | of the following tokens ([I-D.ietf-httpbis-header-structure], | Section 3.9): "same-origin", "same-site", or "cross-site". | | If the "delivery" member contains an unknown identifier, the | member MUST be ignored. ⇒ ---- o Exactly one member whose key is "delivery", and whose value is one of the following tokens ([draft-ietf-httpbis-header-structure-10], Section 3.9): "none", "same-origin", "same-site" [or "same-domain"], or "cross-site". Note: "delivery"'s value "query" is initial value for metadata and not allowed on "Sec-Http-State-Options" response header. ---- Addition: ⇒ ---- o Exactly one member whose key is "confirm" and whose value is one of the following tokens ([draft-ietf-httpbis-header-structure-10], Section 3.9): "deliver", "top", and "block". Note: "confirm"'s value "query" is initial value for metadata and not allowed on "Sec-Http-State-Options" response header. o Exactly one member whose key is "deliver-origins" whose value is string ([draft-ietf-httpbis-header-structure-10], Section 3.8). Value includes comma separated list of origins. ----- 5.1. Attach HTTP State Tokens to a request https://tools.ietf.org/html/draft-west-http-state-tokens-00#section-5.1 | 3. Let "request-token" be the result of retrieving origin's token | from the user agent's token store, or "null" if no such token | exists. I suppose ⇒ ---- 3. Let "request-token" be the result of retrieving target-origin's token from the user agent's token store, or "null" if no such token exists. ---- After step 3 add following step: ⇒ ---- 3a. Execute "get confirm-top-origin" for this request. Result of that algorithm is "confirm-top-origin". Note: This can be null. ---- | 5. If "request-token" is "null", then: | | 1. If "request"'s delivery scope is "cross-site", return | without modifying the request. | | Note: As the default "delivery" for HTTP State Tokens is | "same-site", we return early rather than generating a token | for a cross-site request. | | 2. Set "request-token" to the result of generating an HTTP | State Token for "target-origin", as defined in | Section 3.3.1. ⇒ ---- 5. If "request-token" is "null", then: 1. If "request"'s delivery scope is "cross-site", then execute "attach query" with "reason" value "delivery/confirm" and skip the remaining steps in this algorithm. 2. Set "request-token" to the result of generating an HTTP State Token for "target-origin", as defined in Section 3.3.1. ----- After step 5 add following steps: ⇒ ---- 5a. If "request-token"'s "delivery" is "none", then skip the remaining steps in this algorithm, and return without modifying the request. 5b. If "request-token"'s "delivery" is "query", then: 1. If "request-token"'s "confirm" is "query", execute "attach query" with "reason" value "delivery/confirm" and skip the remaining steps in this algorithm. 2. Execute "attach query" with "reason" value "delivery" and skip the remaining steps in this algorithm. ---- | 6. Return without modifying the request if either of the following | statements are true: | | * "request-token"'s "delivery" is "same-origin", and | "request"'s delivery scope is not "same-origin". | | * "request-token"'s "delivery" is "same-site", and "request"'s | delivery scope is neither "same-origin" nor "same-site". ⇒ ---- 6. Execute "attach void" with "reason" value "delivery" and skip the remaining steps in this algorithm if either of the following statements are true: * "request-token"'s "delivery" is "same-origin", and "request"'s delivery scope is not "same-origin". * "request-token"'s "delivery" is "same-site" [or "same-domain"] , and "request"'s delivery scope is neither "same-origin" nor "same-site". ---- After step 6 add following steps: ⇒ ---- 6a. If "request-token"'s "confirm" is "query", execute "attach query" with "reason" value "confirm" and skip the remaining steps in this algorithm. 6b. If "request-token"'s "confirm" is "top", then: 1. If "confirm-top-origin" is null, execute "attach void" with "reason" value "no-top" and skip the remaining steps in this algorithm. 2. Let "top-token" be the result of retrieving "confirm-top-origin"'s token from the user agent's token store, or "null" if no such token exists. 3. If "top-token" is expired, clear the user agent's token store for "confirm-top-origin", and set "top-token" to "null". 4. If "top-token" is "null", execute "attach void" with "reason" value "top" and skip the remaining steps in this algorithm. 5. If "top-token"'s "deliver-origins" list does not include "target-origin", execute "attach void" with "reason" value "top" and skip the remaining steps in this algorithm. 6c. If "request-token"'s "confirm" is "block", execute "attach void" with "reason" value "confirm" and skip the remaining steps in this algorithm. ---- | 8. Insert a member into "header-value" whose key is "token" and | whose value is "serialized-value". ⇒ ---- 8. Insert a member into "header-value" whose key is "token" and whose value is "serialized-value" (using byte sequence (sh-binary, [draft-ietf-httpbis-header-structure-10], Section 3.10) syntax). ----- | 9. If "request-token"'s "key" is not null, then insert a member | into "header-value" whose key is "sig", and whose value is the | result of executing Section 5.2 on request, "serialized-value", | and "request-token"'s "key". ⇒ Maybe also add note that value is added as a byte sequence: ---- 9. If "request-token"'s "key" is not null, then insert a member into "header-value" whose key is "sig", and whose value as a byte sequence is the result of executing Section 5.2 on request, "serialized-value", and "request-token"'s "key". Base64 Encode a byte sequence and use byte sequence (sh-binary, [draft-ietf-httpbis-header-structure-10], Section 3.10) syntax. ---- Addition: ⇒ ----- "get confirm-top-origin" algorithm is following: 1. Let "top-browsing-context" to be request's client's responsible browsing context or null if request's client is null. Note: Request's client's responsible browsing context may be null. 2. while "top-browsing-context" is not null and "top-browsing-context"'s have a parent browsing context: let "top-browsing-context" to be "top-browsing-context"'s parent browsing context. 3. Let "top-document" to be "top-browsing-context"'s active document or null if "top-browsing-context" is null. 4. Let "confirm-top-origin" to be "top-document"'s origin or null if "top-document" is null. Note: SameSite uses different definition for top-origin. [TBD: SameSite quits when some some ancestor browsing contexts have different registered domain. That is not usable on here. ] [TBD: SameSite looks also sandboxed origin browsing context flag. Should that affect "confirm-top-origin" ? ] [TBD: Not looked what this does for worker-based requests. Perhaps this is OK for "confirm-top-origin". ] [TBD: Some HTTP clients (for example data mining tools) may not instantiate browsing contexts. In that case "confirm-top-origin" is null. ] "attach query" algorithm is following: 1. The user agent MAY omit generating Sec-Http-State: request header if it determines that origin does not support HTTP State Tokens. It is not required that all URL's for the origin responds with Sec-Http-State-Options: response header for query. Note: Sec-Http-State-Options: response header for query may be generated only for certain URLs (for example login and/or front page's URLs). 2. Insert a member into "header-value" whose key is "token" and value is "query" (using token (sh-token, [draft-ietf-httpbis-header-structure-10], Section 3.9) syntax). Note that sh-syntax does not use quotes. 3. Insert a member into "header-value" whose key is "reason" and value is "reason" value for that algorithm (using token (sh-token, [draft-ietf-httpbis-header-structure-10], Section 3.9) syntax). 4. Append a header to "request"'s header list whose name is "Sec- Http-State", and whose value is the result of serializing "header-value" ([draft-ietf-httpbis-header-structure-10], Section 4.1). "attach void" algorithm is following: 1. Insert a member into "header-value" whose key is "token" and value is "void" (using token (sh-token, [draft-ietf-httpbis-header-structure-10], Section 3.9) syntax). Note that sh-syntax does not use quotes. 2. Insert a member into "header-value" whose key is "reason" and value is "reason" value for that algorithm (using token (sh-token, [draft-ietf-httpbis-header-structure-10], Section 3.9) syntax). 3. Append a header to "request"'s header list whose name is "Sec- Http-State", and whose value is the result of serializing "header-value" ([draft-ietf-httpbis-header-structure-10], Section 4.1). ----- 6. Configuring HTTP State Tokens https://tools.ietf.org/html/draft-west-http-state-tokens-00#section-6 | 5. If "token" is "null", then: | | 1. If "request"'s delivery scope is "cross-site", return without | modifying the request. | | Note: As the default "delivery" for HTTP State Tokens is | "same-site", we return early rather than generating a token | for a cross-site request. | | 2. Set "token" to the result of generating an HTTP State Token | for "target-origin", as defined in Section 3.3.1. ⇒ ----- 5. If "token" is "null", then: 1. If "request"'s delivery scope is "cross-site" and response's header list does not contain "Sec-Http-State-Options", return without altering "response-origin"'s HTTP State Token. 2. Set "token" to the result of generating an HTTP State Token for "response-origin", as defined in Section 3.3.1. ----- After step 5 add following step: ⇒ ---- 5a. Execute "get confirm-top-origin" for this request. Result of that algorithm is "confirm-top-origin". Note: This can be null. [TBD: This executed as part of Section 5.2 so "confirm-top-origin" may already be available. ] ----- | 6. If the response's header list contains "Sec-Http-State-Options", | then: On step 6: | 2. Return without altering "response-origin"'s HTTP State Token | if any of the following conditions hold: | | + Parsing the header results in failure. | | + "header" has a member named "key" whose value is not a | byte sequence (Section 3.10 of | [I-D.ietf-httpbis-header-structure]) | | + "header" has a member named "delivery" whose value is not | one of the following tokens (Section 3.9 of | [I-D.ietf-httpbis-header-structure]): "same-origin", | "same-site", and "cross-site". | | + "header" has a member named "max-age" whose value is not a | positive integer (Section 3.6 of | [I-D.ietf-httpbis-header-structure]). ⇒ ---- 2. Return without altering "response-origin"'s HTTP State Token if any of the following conditions hold: + Parsing the header results in failure. + "header" has a member named "key" whose value is not a byte sequence ([draft-ietf-httpbis-header-structure-10], Section 3.10) + "header" has a member named "delivery" whose value is not one of the following tokens ([draft-ietf-httpbis-header-structure-10], Section 3.9): "none", "same-origin", "same-site" [or "same-domain"], and "cross-site". + "header" has a member named "max-age" whose value is not a positive integer ([draft-ietf-httpbis-header-structure-10], Section 3.6). + "header" has a member named "confirm" whose value is not one of the following tokens ([draft-ietf-httpbis-header-structure-10], Section 3.9): "deliver", "top", and "block". + "header" has a member named "deliver-origins" whose value is not a string ([draft-ietf-httpbis-header-structure-10], Section 3.8). ---- Add on step 6 after substep 4 add following steps: ⇒ ---- 4a. If "header" has a member named "confirm", set "token"'s "confirm" to the member's value. 4b. If "header" has a member named "deliver-origins", then: 1. Let "string-value" to be the member's value. 2. Split "string-value" to list using comma as separator. 3. Set "token"'s "deliver-origins" to the resulting list. 4c. If "header" has a member named "confirm", whose value is "top", then: 1. If "confirm-top-origin" is null, skip next substeps. 2. Let "top-token" be the result of retrieving confirm-top-origin's token from the user agent's token store, or "null" if no such token exists. 3. If "top-token" is expired, clear the user agent's token store for "confirm-top-origin", and set "top-token" to "null". 4. If "top-token" is "null", set "top-token" to the result of generating an HTTP State Token for "confirm-top-origin", as defined in Section 3.3.1. 5. If "top-token"'s "query-origins" list does not include "response-origin" value, then: 1. Add "response-origin" to "top-token"'s "query-origins" list. 2. If the user agent has defined a "NotifyHostHTTPStateQuery()" algorithm call it with "confirm-top-origin" and "response-origin" using "top-document"'s environment settings object. / Kari Hurtta
Received on Saturday, 27 April 2019 16:15:27 UTC