Skip to content

Commit 10545d2

Browse files
Integrate with HTTP WG's layered-cookies draft
Co-Authored-By: Anne van Kesteren <[email protected]>
1 parent 0a041eb commit 10545d2

File tree

1 file changed

+173
-41
lines changed

1 file changed

+173
-41
lines changed

fetch.bs

Lines changed: 173 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,29 @@ 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
66+
67+
<!-- TODO: pending HTML changes- ancestor enum (https://github.com/whatwg/html/pull/10559), has storage access bit, initiator origin plumbing -->
68+
urlPrefix:https://html.spec.whatwg.org#;type:dfn;spec:html
69+
url:TODO;text:has cross-site ancestor;for:environment
70+
url:TODO;text:has storage access;for:environment
5771
</pre>
5872

5973
<pre class=biblio>
6074
{
75+
"COOKIES": {
76+
"authors": ["Johann Hofmann", "Anne van Kesteren"],
77+
"href": "https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-layered-cookies",
78+
"title": "Cookies: HTTP State Management Mechanism"
79+
},
6180
"HTTP": {
6281
"aliasOf": "RFC9110"
6382
},
@@ -1961,6 +1980,10 @@ not always relevant and might require different behavior.
19611980
"<code>client</code>" or an <a for=/>origin</a>. Unless stated otherwise it is
19621981
"<code>client</code>".
19631982

1983+
<p>A <a for=/>request</a> has an associated
1984+
<dfn export for=request>top-level navigation initiator origin</dfn>,
1985+
which is an <a for=/>origin</a> or null. Unless stated otherwise it is null.
1986+
19641987
<p class=note>"<code>client</code>" is changed to an <a for=/>origin</a> during
19651988
<a lt=fetch for=/>fetching</a>. It provides a convenient way for standards to not have to set
19661989
<a for=/>request</a>'s <a for=request>origin</a>.
@@ -2249,31 +2272,39 @@ or "<code>object</code>".
22492272
<hr>
22502273

22512274
<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:
2275+
<p>To compute the <dfn for=request id=concept-request-tainted-origin>redirect-taint</dfn> of a
2276+
<a for=/>request</a> <var>request</var>, perform the following steps. They return
2277+
"<code>same-origin</code>", "<code>same-site</code>", or "<code>cross-site</code>".
22552278

22562279
<ol>
22572280
<li><p><a for=/>Assert</a>: <var>request</var>'s <a for=request>origin</a> is not
22582281
"<code>client</code>".
22592282

22602283
<li><p>Let <var>lastURL</var> be null.
22612284

2285+
<li><p>Let <var>computedTaint</var> be "<code>same-origin</code>".
2286+
22622287
<li>
22632288
<p><a for=list>For each</a> <var>url</var> of <var>request</var>'s <a for=request>URL list</a>:
22642289

22652290
<ol>
22662291
<li><p>If <var>lastURL</var> is null, then set <var>lastURL</var> to <var>url</var> and
22672292
<a for=iteration>continue</a>.
22682293

2294+
<li><p>If <var>url</var>'s <a for=url>origin</a> is not <a for=/>same site</a> with
2295+
<var>lastURL</var>'s <a for=url>origin</a> and <var>request</var>'s <a for=request>origin</a> is
2296+
not <a for=/>same site</a> with <var>lastURL</var>'s <a for=url>origin</a>, then return
2297+
"<code>cross-site</code>".
2298+
22692299
<li><p>If <var>url</var>'s <a for=url>origin</a> is not <a>same origin</a> with
22702300
<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.
2301+
not <a>same origin</a> with <var>lastURL</var>'s <a for=url>origin</a>, then set
2302+
<var>computedTaint</var> to "<code>same-site</code>".
22722303

22732304
<li>Set <var>lastURL</var> to <var>url</var>.
22742305
</ol>
22752306

2276-
<li>Return false.
2307+
<li><p>Return <var>computedTaint</var>.
22772308
</ol>
22782309
</div>
22792310

@@ -2285,8 +2316,8 @@ run these steps:
22852316
<li><p><a for=/>Assert</a>: <var>request</var>'s <a for=request>origin</a> is not
22862317
"<code>client</code>".
22872318

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

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

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

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

23922423
<li><p>If <var>request</var>'s <a for=request>client</a>'s
23932424
<a for="environment settings object">policy container</a>'s
23942425
<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>
2426+
"<a for="embedder policy value"><code>credentialless</code></a>", then return true.
23962427

23972428
<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>
2429+
<var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a> and <var>request</var>'s
2430+
<a for=request>redirect-taint</a> is not "<code>same-origin</code>", then return true.
24002431

2401-
<li><p>Return false.</p>
2432+
<li><p>Return false.
24022433
</ol>
24032434
</div>
24042435

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

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.
2543+
<p>A <a for=/>response</a> has an associated <dfn for=response>redirect taint</dfn>
2544+
("<code>same-origin</code>", "<code>same-site</code>", or "<code>cross-site</code>"), which is
2545+
initially "<code>same-origin</code>".
25142546

25152547
<hr>
25162548

@@ -4252,6 +4284,125 @@ prefetch, or to treat it differently when counting page visits.
42524284

42534285

42544286

4287+
<h2 id=cookies>Cookies</h2>
4288+
4289+
<h3 id=cookie-header>`<code>Cookie</code>` header</h3>
4290+
4291+
<p>The `<code>Cookie</code>` header is largely defined in its own specification. We define
4292+
additional infrastructure to be able to use them conveniently here. [[COOKIES]].
4293+
4294+
<div algorithm>
4295+
<p>To <dfn>append a request `<code>Cookie</code>` header</dfn>,
4296+
given a <a for=/>request</a> <var>request</var>:
4297+
4298+
<ol>
4299+
<li><p>If the user agent is configured to disable cookies for <var>request</var>, then it should
4300+
return.
4301+
4302+
<li><p>Let |sameSite| be the result of [=determining the same-site mode=] for <var>request</var>.
4303+
4304+
<li><p>Let |isSecure| be false.
4305+
4306+
<li><p>If <var>request</var>'s <a for=request>client</a> is a <a>secure context</a>, then set
4307+
|isSecure| to true.
4308+
4309+
<li>
4310+
<p>Let |httpOnlyAllowed| be true.
4311+
4312+
<p class=note>True follows from this being invoked from <a>fetch</a>, as opposed to the
4313+
<code>document.cookie</code> getter steps for instance.
4314+
4315+
<li>
4316+
<p>Let |cookies| be the result of running <a>retrieve cookies</a> given |isSecure|,
4317+
<var>request</var>'s <a for=request>current URL</a>'s <a for=url>host</a>, <var>request</var>'s
4318+
<a for=request>current URL</a>'s <a for=url>path</a>, |httpOnlyAllowed|, and |sameSite|.
4319+
4320+
<p class=note>The cookie store returns an ordered list of cookies
4321+
4322+
<li><p>If |cookies| <a for="list">is empty</a>, then return.
4323+
4324+
<li><p>Let |value| be the result of running <a>serialize cookies</a> given |cookies|.
4325+
4326+
<li><p><a for="header list">Append</a> (`<code>Cookie</code>`, <var>value</var>) to
4327+
<var>request</var>'s <a for=request>header list</a>.
4328+
</ol>
4329+
</div>
4330+
4331+
<div algorithm>
4332+
<p>To
4333+
<dfn>parse and store response `<code>Set-Cookie</code>` headers</dfn>,
4334+
given a <a for=/>request</a> <var>request</var> and a <a for=/>response</a> <var>response</var>:
4335+
4336+
<ol>
4337+
<li><p>If the user agent is configured to disable cookies for <var>request</var>,
4338+
then it should return.
4339+
4340+
<li><p>Let |allowNonHostOnlyCookieForPublicSuffix| be false.
4341+
4342+
<li><p>Let |isSecure| be false.
4343+
4344+
<li><p>If <var>request</var>'s <a for=request>current URL</a>'s <a for=url>scheme</a> is
4345+
"<code>https</code>", then set |isSecure| to true.
4346+
4347+
<li>
4348+
<p>Let |httpOnlyAllowed| be true.
4349+
4350+
<p class=note>True follows from this being invoked from <a>fetch</a>, as opposed to the
4351+
<code>document.cookie</code> getter steps for instance.
4352+
4353+
<li><p>Let |sameSiteStrictOrLaxAllowed| be true if the result of [=determine the same-site mode=]
4354+
for |request| is "<code>StrictOrLess</code>", and false otherwise.
4355+
4356+
<li><p><a for=list>For each</a> <var>header</var> of <var>response</var>'s
4357+
<a for=response>header list</a>:
4358+
4359+
<ol>
4360+
<li><p>If <var>header</var>'s <a for=header>name</a> is not a <a>byte-case-insensitive</a> match
4361+
for `<code>Set-Cookie</code>`, <a for=iteration>continue</a>.
4362+
4363+
<li><p><a>Parse and store a cookie</a> given <var>header</var>'s <a for=header>value</a>,
4364+
|isSecure|, <var>request</var>'s <a for=request>current URL</a>'s <a for=url>host</a>,
4365+
<var>request</var>'s <a for=request>current URL</a>'s <a for=url>path</a>, |httpOnlyAllowed|,
4366+
|allowNonHostOnlyCookieForPublicSuffix|, and |sameSiteStrictOrLaxAllowed|.
4367+
4368+
<li><p><a>Garbage collect cookies</a> given <var>request</var>'s
4369+
<a for=request>current URL</a>'s <a for=url>host</a>.
4370+
</ol>
4371+
</ol>
4372+
</div>
4373+
4374+
<h3 id=cookie-infrastructure>Cookie infrastructure</h3>
4375+
4376+
<p>These algorithms are not only for use with the `<code>Cookie</code>` header, and are used in
4377+
other specifications.
4378+
4379+
<div algorithm>
4380+
<p>To <dfn>determine the same-site mode</dfn> for a given <a for=/>request</a> <var>request</var>:
4381+
4382+
<ol>
4383+
<li><p><a for=/>Assert</a>: <var>request</var>'s <a for=request>method</a> is "<code>GET</code>"
4384+
or "<code>POST</code>".
4385+
4386+
<li><p>If <var>request</var>'s <a for=request>top-level navigation initiator origin</a> is not
4387+
null and is not <a for=/>same site</a> to <var>request</var>'s <a for=request>URL</a>'s
4388+
<a for=url>origin</a>, then return "<code>UnsetOrLess</code>".
4389+
4390+
<li><p>If <var>request</var>'s <a for=request>method</a> is "<code>GET</code>" and
4391+
<var>request</var>'s <a for=request>destination</a> is "document", then return
4392+
"<code>LaxOrLess</code>".
4393+
4394+
<li><p>If <var>request</var>'s <a for=request>client</a>'s
4395+
<a for=environment>has cross-site ancestor</a> is true then return "<code>UnsetOrLess</code>".
4396+
4397+
<li><p>If <var>request</var>'s <a for=request>redirect-taint</a> is "<code>cross-site</code>",
4398+
then return "<code>UnsetOrLess</code>".
4399+
4400+
<li><p>Return "<code>StrictOrLess</code>".
4401+
</ol>
4402+
</div>
4403+
4404+
4405+
42554406
<h2 id=fetching>Fetching</h2>
42564407

42574408
<p class=note>The algorithm below defines <a lt=fetch for=/>fetching</a>. In broad strokes, it takes
@@ -4729,8 +4880,8 @@ steps:
47294880
<!-- If you are ever tempted to move this around, carefully consider responses from about URLs,
47304881
blob URLs, service workers, HTTP cache, HTTP network, etc. -->
47314882

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.
4883+
<li><p>Set <var>internalResponse</var>'s <a for=response>redirect taint</a> to <var>request</var>'s
4884+
<a for=request>redirect-taint</a>.
47344885

47354886
<li><p>If <var>request</var>'s <a for=request>timing allow failed flag</a> is unset, then set
47364887
<var>internalResponse</var>'s <a for=response>timing allow passed flag</a>.
@@ -4883,7 +5034,7 @@ steps:
48835034
<li>
48845035
<p>If <var>fetchParams</var>'s <a for="fetch params">request</a>'s <a for=request>mode</a> is
48855036
not "<code>navigate</code>" or <var>response</var>'s
4886-
<a for=response>has-cross-origin-redirects</a> is false:
5037+
<a for=response>redirect taint</a> is "<code>same-origin</code>":
48875038

48885039
<ol>
48895040
<li><p>Set <var>responseStatus</var> to <var>response</var>'s <a for=response>status</a>.
@@ -5766,21 +5917,7 @@ run these steps:
57665917
<p>If <var>includeCredentials</var> is true, then:
57675918

57685919
<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>
5920+
<li><p><a>Append a request `<code>Cookie</code>` header</a> for <var>httpRequest</var>.
57845921

57855922
<li>
57865923
<p>If <var>httpRequest</var>'s <a for=request>header list</a>
@@ -6343,14 +6480,9 @@ optional boolean <var>forceNewConnection</var> (default false), run these steps:
63436480
<li><p>Set <var>response</var>'s <a for=response>body</a> to a new <a for=/>body</a> whose
63446481
<a for=body>stream</a> is <var>stream</var>.
63456482

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>.
6483+
<li><p tracking-vector>If <var>includeCredentials</var> is true, then the user agent should
6484+
<a>parse and store response `<code>Set-Cookie</code>` headers</a> given <var>request</var> and
6485+
<var>response</var>.
63546486

63556487
<li>
63566488
<p>Run these steps <a>in parallel</a>:

0 commit comments

Comments
 (0)