Skip to content

Commit 1d9380b

Browse files
bvandersloot-mozillajohannhofannevk
authored
Integrate with HTTP WG's layered-cookies work
This builds on whatwg/html#10991 and whatwg/html#11133. This should be a mostly editorial change, but with much more clarity about how the state flows into the IETF side. Co-authored-by: Johann Hofmann <[email protected]> Co-authored-by: Anne van Kesteren <[email protected]>
1 parent 0a041eb commit 1d9380b

File tree

1 file changed

+172
-42
lines changed

1 file changed

+172
-42
lines changed

fetch.bs

Lines changed: 172 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,24 @@ urlPrefix:https://tc39.es/ecma262/#;type:dfn;spec:ecma-262
5454
url:realm;text:realm
5555
url:sec-list-and-record-specification-type;text:Record
5656
url:current-realm;text:current realm
57+
58+
urlPrefix:https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-layered-cookies#;type:dfn;spec:cookies
59+
url:name-cookie-store-and-limits;text:cookie store
60+
url:name-parse-and-store-a-cookie;text:parse and store a cookie
61+
url:name-parse-a-cookie;text:parse a cookie
62+
url:name-store-a-cookie;text:store a cookie
63+
url:name-retrieve-cookies;text:retrieve cookies
64+
url:name-serialize-cookies;text:serialize cookies
65+
url:name-garbage-collect-cookies;text:garbage collect cookies
5766
</pre>
5867

5968
<pre class=biblio>
6069
{
70+
"COOKIES": {
71+
"authors": ["Johann Hofmann", "Anne van Kesteren"],
72+
"href": "https://httpwg.org/http-extensions/draft-ietf-httpbis-layered-cookies.html",
73+
"title": "Cookies: HTTP State Management Mechanism"
74+
},
6175
"HTTP": {
6276
"aliasOf": "RFC9110"
6377
},
@@ -1965,6 +1979,10 @@ not always relevant and might require different behavior.
19651979
<a lt=fetch for=/>fetching</a>. It provides a convenient way for standards to not have to set
19661980
<a for=/>request</a>'s <a for=request>origin</a>.
19671981

1982+
<p>A <a for=/>request</a> has an associated
1983+
<dfn export for=request>top-level navigation initiator origin</dfn>, which is an <a for=/>origin</a>
1984+
or null. Unless stated otherwise it is null.
1985+
19681986
<p>A <a for=/>request</a> has an associated
19691987
<dfn export for=request id=concept-request-policy-container>policy container</dfn>, which is
19701988
"<code>client</code>" or a <a for=/>policy container</a>. Unless stated otherwise it is
@@ -2249,31 +2267,39 @@ or "<code>object</code>".
22492267
<hr>
22502268

22512269
<div algorithm>
2252-
<p>A <a for=/>request</a> <var>request</var> has a
2253-
<dfn for=request id=concept-request-tainted-origin>redirect-tainted origin</dfn> if these steps
2254-
return true:
2270+
<p>To compute the <dfn for=request id=concept-request-tainted-origin>redirect-taint</dfn> of a
2271+
<a for=/>request</a> <var>request</var>, perform the following steps. They return
2272+
"<code>same-origin</code>", "<code>same-site</code>", or "<code>cross-site</code>".
22552273

22562274
<ol>
22572275
<li><p><a for=/>Assert</a>: <var>request</var>'s <a for=request>origin</a> is not
22582276
"<code>client</code>".
22592277

22602278
<li><p>Let <var>lastURL</var> be null.
22612279

2280+
<li><p>Let <var>taint</var> be "<code>same-origin</code>".
2281+
22622282
<li>
22632283
<p><a for=list>For each</a> <var>url</var> of <var>request</var>'s <a for=request>URL list</a>:
22642284

22652285
<ol>
22662286
<li><p>If <var>lastURL</var> is null, then set <var>lastURL</var> to <var>url</var> and
22672287
<a for=iteration>continue</a>.
22682288

2289+
<li><p>If <var>url</var>'s <a for=url>origin</a> is not <a for=/>same site</a> with
2290+
<var>lastURL</var>'s <a for=url>origin</a> and <var>request</var>'s <a for=request>origin</a> is
2291+
not <a for=/>same site</a> with <var>lastURL</var>'s <a for=url>origin</a>, then return
2292+
"<code>cross-site</code>".
2293+
22692294
<li><p>If <var>url</var>'s <a for=url>origin</a> is not <a>same origin</a> with
22702295
<var>lastURL</var>'s <a for=url>origin</a> and <var>request</var>'s <a for=request>origin</a> is
2271-
not <a>same origin</a> with <var>lastURL</var>'s <a for=url>origin</a>, then return true.
2296+
not <a>same origin</a> with <var>lastURL</var>'s <a for=url>origin</a>, then set
2297+
<var>taint</var> to "<code>same-site</code>".
22722298

2273-
<li>Set <var>lastURL</var> to <var>url</var>.
2299+
<li><p>Set <var>lastURL</var> to <var>url</var>.
22742300
</ol>
22752301

2276-
<li>Return false.
2302+
<li><p>Return <var>taint</var>.
22772303
</ol>
22782304
</div>
22792305

@@ -2285,8 +2311,8 @@ run these steps:
22852311
<li><p><a for=/>Assert</a>: <var>request</var>'s <a for=request>origin</a> is not
22862312
"<code>client</code>".
22872313

2288-
<li><p>If <var>request</var> has a <a for=request>redirect-tainted origin</a>, then return
2289-
"<code>null</code>".
2314+
<li><p>If <var>request</var>'s <a for=request>redirect-taint</a> is not "<code>same-origin</code>",
2315+
then return "<code>null</code>".
22902316

22912317
<li><p>Return <var>request</var>'s <a for=request>origin</a>,
22922318
<a lt="ASCII serialization of an origin">serialized</a>.
@@ -2385,20 +2411,20 @@ source of security bugs. Please seek security review for features that deal with
23852411
"<code>client</code>".
23862412

23872413
<li><p>If <var>request</var>'s <a for=request>mode</a> is not "<code>no-cors</code>", then return
2388-
true.</p>
2414+
true.
23892415

2390-
<li><p>If <var>request</var>'s <a for=request>client</a> is null, then return true.</p>
2416+
<li><p>If <var>request</var>'s <a for=request>client</a> is null, then return true.
23912417

23922418
<li><p>If <var>request</var>'s <a for=request>client</a>'s
23932419
<a for="environment settings object">policy container</a>'s
23942420
<a for="policy container">embedder policy</a>'s <a for="embedder policy">value</a> is not
2395-
"<a for="embedder policy value"><code>credentialless</code></a>", then return true.</p>
2421+
"<a for="embedder policy value"><code>credentialless</code></a>", then return true.
23962422

23972423
<li><p>If <var>request</var>'s <a for=request>origin</a> is <a>same origin</a> with
2398-
<var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a> and <var>request</var>
2399-
does not have a <a for=request>redirect-tainted origin</a>, then return true.</p>
2424+
<var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a> and <var>request</var>'s
2425+
<a for=request>redirect-taint</a> is not "<code>same-origin</code>", then return true.
24002426

2401-
<li><p>Return false.</p>
2427+
<li><p>Return false.
24022428
</ol>
24032429
</div>
24042430

@@ -2509,8 +2535,9 @@ this is also tracked internally using the request's <a for=request>timing allow
25092535
<dfn export for=response>service worker timing info</dfn> (null or a
25102536
<a for=/>service worker timing info</a>), which is initially null.
25112537

2512-
<p>A <a for=/>response</a> has an associated <dfn for=response>has-cross-origin-redirects</dfn>
2513-
(a boolean), which is initially false.
2538+
<p>A <a for=/>response</a> has an associated <dfn for=response>redirect taint</dfn>
2539+
("<code>same-origin</code>", "<code>same-site</code>", or "<code>cross-site</code>"), which is
2540+
initially "<code>same-origin</code>".
25142541

25152542
<hr>
25162543

@@ -3315,6 +3342,127 @@ through TLS using ALPN. The protocol cannot be spoofed through HTTP requests in
33153342

33163343
<h2 id=http-extensions>HTTP extensions</h2>
33173344

3345+
<h3 id=cookies>Cookies</h3>
3346+
3347+
<p>The `<code>Cookie</code>` request header and `<code>Set-Cookie</code>` response headers are
3348+
largely defined in their own specifications. We define additional infrastructure to be able to use
3349+
them conveniently here. [[COOKIES]].
3350+
3351+
3352+
<h4 id=cookie-header>`<code>Cookie</code>` header</h4>
3353+
3354+
<div algorithm>
3355+
<p>To <dfn>append a request `<code>Cookie</code>` header</dfn>, given a <a for=/>request</a>
3356+
<var>request</var>:
3357+
3358+
<ol>
3359+
<li><p>If the user agent is configured to disable cookies for <var>request</var>, then it should
3360+
return.
3361+
3362+
<li><p>Let |sameSite| be the result of [=determining the same-site mode=] for <var>request</var>.
3363+
3364+
<li><p>Let |isSecure| be true if <var>request</var>'s <a for=request>current URL</a>'s
3365+
<a for=url>scheme</a> is "<code>https</code>"; otherwise false.
3366+
3367+
<li>
3368+
<p>Let |httpOnlyAllowed| be true.
3369+
3370+
<p class=note>True follows from this being invoked from <a>fetch</a>, as opposed to the
3371+
<code>document.cookie</code> getter steps for instance.
3372+
3373+
<li>
3374+
<p>Let |cookies| be the result of running <a>retrieve cookies</a> given |isSecure|,
3375+
<var>request</var>'s <a for=request>current URL</a>'s <a for=url>host</a>, <var>request</var>'s
3376+
<a for=request>current URL</a>'s <a for=url>path</a>, |httpOnlyAllowed|, and |sameSite|.
3377+
3378+
<p class=note>The cookie store returns an ordered list of cookies
3379+
3380+
<li><p>If |cookies| <a for="list">is empty</a>, then return.
3381+
3382+
<li><p>Let |value| be the result of running <a>serialize cookies</a> given |cookies|.
3383+
3384+
<li><p><a for="header list">Append</a> (`<code>Cookie</code>`, <var>value</var>) to
3385+
<var>request</var>'s <a for=request>header list</a>.
3386+
</ol>
3387+
</div>
3388+
3389+
3390+
<h4 id=set-cookie-header>`<code>Set-Cookie</code>` header</h4>
3391+
3392+
<div algorithm>
3393+
<p>To <dfn>parse and store response `<code>Set-Cookie</code>` headers</dfn>, given a
3394+
<a for=/>request</a> <var>request</var> and a <a for=/>response</a> <var>response</var>:
3395+
3396+
<ol>
3397+
<li><p>If the user agent is configured to disable cookies for <var>request</var>, then it should
3398+
return.
3399+
3400+
<li><p>Let |allowNonHostOnlyCookieForPublicSuffix| be false.
3401+
3402+
<li><p>Let |isSecure| be true if <var>request</var>'s <a for=request>current URL</a>'s
3403+
<a for=url>scheme</a> is "<code>https</code>"; otherwise false.
3404+
3405+
<li>
3406+
<p>Let |httpOnlyAllowed| be true.
3407+
3408+
<p class=note>True follows from this being invoked from <a>fetch</a>, as opposed to the
3409+
<code>document.cookie</code> getter steps for instance.
3410+
3411+
<li><p>Let |sameSiteStrictOrLaxAllowed| be true if the result of [=determine the same-site mode=]
3412+
for |request| is "<code>strict-or-less</code>"; otherwise false.
3413+
3414+
<li>
3415+
<p><a for=list>For each</a> <var>header</var> of <var>response</var>'s
3416+
<a for=response>header list</a>:
3417+
3418+
<ol>
3419+
<li><p>If <var>header</var>'s <a for=header>name</a> is not a <a>byte-case-insensitive</a> match
3420+
for `<code>Set-Cookie</code>`, then <a for=iteration>continue</a>.
3421+
3422+
<li><p><a>Parse and store a cookie</a> given <var>header</var>'s <a for=header>value</a>,
3423+
|isSecure|, <var>request</var>'s <a for=request>current URL</a>'s <a for=url>host</a>,
3424+
<var>request</var>'s <a for=request>current URL</a>'s <a for=url>path</a>, |httpOnlyAllowed|,
3425+
|allowNonHostOnlyCookieForPublicSuffix|, and |sameSiteStrictOrLaxAllowed|.
3426+
3427+
<li><p><a>Garbage collect cookies</a> given <var>request</var>'s <a for=request>current URL</a>'s
3428+
<a for=url>host</a>.
3429+
</ol>
3430+
3431+
<p class=note>As noted elsewhere the `<code>Set-Cookie</code>` header cannot be combined and
3432+
therefore each occurrence is processed independently. This is not allowed for any other header.
3433+
</ol>
3434+
</div>
3435+
3436+
3437+
<h4 id=cookie-infrastructure>Cookie infrastructure</h4>
3438+
3439+
<div algorithm>
3440+
<p>To <dfn>determine the same-site mode</dfn> for a given <a for=/>request</a> <var>request</var>:
3441+
3442+
<ol>
3443+
<li><p><a for=/>Assert</a>: <var>request</var>'s <a for=request>method</a> is "<code>GET</code>"
3444+
or "<code>POST</code>".
3445+
3446+
<li><p>If <var>request</var>'s <a for=request>top-level navigation initiator origin</a> is not
3447+
null and is not <a for=/>same site</a> with <var>request</var>'s <a for=request>URL</a>'s
3448+
<a for=url>origin</a>, then return "<code>unset-or-less</code>".
3449+
3450+
<li><p>If <var>request</var>'s <a for=request>method</a> is "<code>GET</code>" and
3451+
<var>request</var>'s <a for=request>destination</a> is "document", then return
3452+
"<code>lax-or-less</code>".
3453+
3454+
<li><p>If <var>request</var>'s <a for=request>client</a>'s
3455+
<a for="environment settings object">has cross-site ancestor</a> is true, then return
3456+
"<code>unset-or-less</code>".
3457+
3458+
<li><p>If <var>request</var>'s <a for=request>redirect-taint</a> is "<code>cross-site</code>", then
3459+
return "<code>unset-or-less</code>".
3460+
3461+
<li><p>Return "<code>strict-or-less</code>".
3462+
</ol>
3463+
</div>
3464+
3465+
33183466
<h3 id=origin-header>`<code>Origin</code>` header</h3>
33193467

33203468
<p>The `<dfn export http-header id=http-origin><code>Origin</code></dfn>`
@@ -4729,8 +4877,8 @@ steps:
47294877
<!-- If you are ever tempted to move this around, carefully consider responses from about URLs,
47304878
blob URLs, service workers, HTTP cache, HTTP network, etc. -->
47314879

4732-
<li><p>If <var>request</var> has a <a for=request>redirect-tainted origin</a>, then set
4733-
<var>internalResponse</var>'s <a for=response>has-cross-origin-redirects</a> to true.
4880+
<li><p>Set <var>internalResponse</var>'s <a for=response>redirect taint</a> to <var>request</var>'s
4881+
<a for=request>redirect-taint</a>.
47344882

47354883
<li><p>If <var>request</var>'s <a for=request>timing allow failed flag</a> is unset, then set
47364884
<var>internalResponse</var>'s <a for=response>timing allow passed flag</a>.
@@ -4883,7 +5031,7 @@ steps:
48835031
<li>
48845032
<p>If <var>fetchParams</var>'s <a for="fetch params">request</a>'s <a for=request>mode</a> is
48855033
not "<code>navigate</code>" or <var>response</var>'s
4886-
<a for=response>has-cross-origin-redirects</a> is false:
5034+
<a for=response>redirect taint</a> is "<code>same-origin</code>":
48875035

48885036
<ol>
48895037
<li><p>Set <var>responseStatus</var> to <var>response</var>'s <a for=response>status</a>.
@@ -5766,21 +5914,7 @@ run these steps:
57665914
<p>If <var>includeCredentials</var> is true, then:
57675915

57685916
<ol>
5769-
<li>
5770-
<p>If the user agent is not configured to block cookies for <var>httpRequest</var> (see
5771-
<a href=https://httpwg.org/specs/rfc6265.html#privacy-considerations>section 7</a> of
5772-
[[!COOKIES]]), then:
5773-
5774-
<ol>
5775-
<li><p>Let <var>cookies</var> be the result of running the "cookie-string" algorithm (see
5776-
<a href=https://httpwg.org/specs/rfc6265.html#cookie>section 5.4</a> of
5777-
[[!COOKIES]]) with the user agent's cookie store and <var>httpRequest</var>'s
5778-
<a for=request>current URL</a>.
5779-
5780-
<li>If <var>cookies</var> is not the empty string, then <a for="header list">append</a>
5781-
(`<code>Cookie</code>`, <var>cookies</var>) to <var>httpRequest</var>'s
5782-
<a for=request>header list</a>.
5783-
</ol>
5917+
<li><p><a>Append a request `<code>Cookie</code>` header</a> for <var>httpRequest</var>.
57845918

57855919
<li>
57865920
<p>If <var>httpRequest</var>'s <a for=request>header list</a>
@@ -6343,14 +6477,9 @@ optional boolean <var>forceNewConnection</var> (default false), run these steps:
63436477
<li><p>Set <var>response</var>'s <a for=response>body</a> to a new <a for=/>body</a> whose
63446478
<a for=body>stream</a> is <var>stream</var>.
63456479

6346-
<li><p tracking-vector>If <var>includeCredentials</var> is true and the user agent is not
6347-
configured to block cookies for <var>request</var> (see
6348-
<a href=https://httpwg.org/specs/rfc6265.html#privacy-considerations>section 7</a> of
6349-
[[!COOKIES]]), then run the "set-cookie-string" parsing algorithm (see
6350-
<a href=https://httpwg.org/specs/rfc6265.html#set-cookie>section 5.2</a> of [[!COOKIES]]) on the
6351-
<a for=header>value</a> of each <a for=/>header</a> whose <a for=header>name</a> is a
6352-
<a>byte-case-insensitive</a> match for `<code>Set-Cookie</code>` in <var>response</var>'s
6353-
<a for=response>header list</a>, if any, and <var>request</var>'s <a for=request>current URL</a>.
6480+
<li><p tracking-vector>If <var>includeCredentials</var> is true, then the user agent should
6481+
<a>parse and store response `<code>Set-Cookie</code>` headers</a> given <var>request</var> and
6482+
<var>response</var>.
63546483

63556484
<li>
63566485
<p>Run these steps <a>in parallel</a>:
@@ -9156,6 +9285,7 @@ Axel Rauschmayer,
91569285
Ben Kelly,
91579286
Benjamin Gruenbaum,
91589287
Benjamin Hawkes-Lewis,
9288+
Benjamin VanderSloot,
91599289
Bert Bos,
91609290
Björn Höhrmann,
91619291
Boris Zbarsky,

0 commit comments

Comments
 (0)