Skip to content

Commit 48f6356

Browse files
Integrate with HTTP WG's layered-cookies draft
Co-Authored-By: Anne van Kesteren <[email protected]>
1 parent 07662d3 commit 48f6356

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
},
@@ -1938,6 +1957,10 @@ not always relevant and might require different behavior.
19381957
"<code>client</code>" or an <a for=/>origin</a>. Unless stated otherwise it is
19391958
"<code>client</code>".
19401959

1960+
<p>A <a for=/>request</a> has an associated
1961+
<dfn export for=request>top-level navigation initiator origin</dfn>,
1962+
which is an <a for=/>origin</a> or null. Unless stated otherwise it is null.
1963+
19411964
<p class=note>"<code>client</code>" is changed to an <a for=/>origin</a> during
19421965
<a lt=fetch for=/>fetching</a>. It provides a convenient way for standards to not have to set
19431966
<a for=/>request</a>'s <a for=request>origin</a>.
@@ -2226,31 +2249,39 @@ or "<code>object</code>".
22262249
<hr>
22272250

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

22332256
<ol>
22342257
<li><p><a for=/>Assert</a>: <var>request</var>'s <a for=request>origin</a> is not
22352258
"<code>client</code>".
22362259

22372260
<li><p>Let <var>lastURL</var> be null.
22382261

2262+
<li><p>Let <var>computedTaint</var> be "<code>same-origin</code>".
2263+
22392264
<li>
22402265
<p><a for=list>For each</a> <var>url</var> of <var>request</var>'s <a for=request>URL list</a>:
22412266

22422267
<ol>
22432268
<li><p>If <var>lastURL</var> is null, then set <var>lastURL</var> to <var>url</var> and
22442269
<a for=iteration>continue</a>.
22452270

2271+
<li><p>If <var>url</var>'s <a for=url>origin</a> is not <a for=/>same site</a> with
2272+
<var>lastURL</var>'s <a for=url>origin</a> and <var>request</var>'s <a for=request>origin</a> is
2273+
not <a for=/>same site</a> with <var>lastURL</var>'s <a for=url>origin</a>, then return
2274+
"<code>cross-site</code>".
2275+
22462276
<li><p>If <var>url</var>'s <a for=url>origin</a> is not <a>same origin</a> with
22472277
<var>lastURL</var>'s <a for=url>origin</a> and <var>request</var>'s <a for=request>origin</a> is
2248-
not <a>same origin</a> with <var>lastURL</var>'s <a for=url>origin</a>, then return true.
2278+
not <a>same origin</a> with <var>lastURL</var>'s <a for=url>origin</a>, then set
2279+
<var>computedTaint</var> to "<code>same-site</code>".
22492280

22502281
<li>Set <var>lastURL</var> to <var>url</var>.
22512282
</ol>
22522283

2253-
<li>Return false.
2284+
<li><p>Return <var>computedTaint</var>.
22542285
</ol>
22552286
</div>
22562287

@@ -2262,8 +2293,8 @@ run these steps:
22622293
<li><p><a for=/>Assert</a>: <var>request</var>'s <a for=request>origin</a> is not
22632294
"<code>client</code>".
22642295

2265-
<li><p>If <var>request</var> has a <a for=request>redirect-tainted origin</a>, then return
2266-
"<code>null</code>".
2296+
<li><p>If <var>request</var>'s <a for=request>redirect-taint</a> is not "<code>same-origin</code>",
2297+
then return "<code>null</code>".
22672298

22682299
<li><p>Return <var>request</var>'s <a for=request>origin</a>,
22692300
<a lt="ASCII serialization of an origin">serialized</a>.
@@ -2362,20 +2393,20 @@ source of security bugs. Please seek security review for features that deal with
23622393
"<code>client</code>".
23632394

23642395
<li><p>If <var>request</var>'s <a for=request>mode</a> is not "<code>no-cors</code>", then return
2365-
true.</p>
2396+
true.
23662397

2367-
<li><p>If <var>request</var>'s <a for=request>client</a> is null, then return true.</p>
2398+
<li><p>If <var>request</var>'s <a for=request>client</a> is null, then return true.
23682399

23692400
<li><p>If <var>request</var>'s <a for=request>client</a>'s
23702401
<a for="environment settings object">policy container</a>'s
23712402
<a for="policy container">embedder policy</a>'s <a for="embedder policy">value</a> is not
2372-
"<a for="embedder policy value"><code>credentialless</code></a>", then return true.</p>
2403+
"<a for="embedder policy value"><code>credentialless</code></a>", then return true.
23732404

23742405
<li><p>If <var>request</var>'s <a for=request>origin</a> is <a>same origin</a> with
2375-
<var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a> and <var>request</var>
2376-
does not have a <a for=request>redirect-tainted origin</a>, then return true.</p>
2406+
<var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a> and <var>request</var>'s
2407+
<a for=request>redirect-taint</a> is not "<code>same-origin</code>", then return true.
23772408

2378-
<li><p>Return false.</p>
2409+
<li><p>Return false.
23792410
</ol>
23802411
</div>
23812412

@@ -2486,8 +2517,9 @@ this is also tracked internally using the request's <a for=request>timing allow
24862517
<dfn export for=response>service worker timing info</dfn> (null or a
24872518
<a for=/>service worker timing info</a>), which is initially null.
24882519

2489-
<p>A <a for=/>response</a> has an associated <dfn for=response>has-cross-origin-redirects</dfn>
2490-
(a boolean), which is initially false.
2520+
<p>A <a for=/>response</a> has an associated <dfn for=response>redirect taint</dfn>
2521+
("<code>same-origin</code>", "<code>same-site</code>", or "<code>cross-site</code>"), which is
2522+
initially "<code>same-origin</code>".
24912523

24922524
<hr>
24932525

@@ -4227,6 +4259,125 @@ prefetch, or to treat it differently when counting page visits.
42274259

42284260

42294261

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

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

4683-
<li><p>If <var>request</var> has a <a for=request>redirect-tainted origin</a>, then set
4684-
<var>internalResponse</var>'s <a for=response>has-cross-origin-redirects</a> to true.
4834+
<li><p>Set <var>internalResponse</var>'s <a for=response>redirect taint</a> to <var>request</var>'s
4835+
<a for=request>redirect-taint</a>.
46854836

46864837
<li><p>If <var>request</var>'s <a for=request>timing allow failed flag</a> is unset, then set
46874838
<var>internalResponse</var>'s <a for=response>timing allow passed flag</a>.
@@ -4834,7 +4985,7 @@ steps:
48344985
<li>
48354986
<p>If <var>fetchParams</var>'s <a for="fetch params">request</a>'s <a for=request>mode</a> is
48364987
not "<code>navigate</code>" or <var>response</var>'s
4837-
<a for=response>has-cross-origin-redirects</a> is false:
4988+
<a for=response>redirect taint</a> is "<code>same-origin</code>":
48384989

48394990
<ol>
48404991
<li><p>Set <var>responseStatus</var> to <var>response</var>'s <a for=response>status</a>.
@@ -5710,21 +5861,7 @@ run these steps:
57105861
<p>If <var>includeCredentials</var> is true, then:
57115862

57125863
<ol>
5713-
<li>
5714-
<p>If the user agent is not configured to block cookies for <var>httpRequest</var> (see
5715-
<a href=https://httpwg.org/specs/rfc6265.html#privacy-considerations>section 7</a> of
5716-
[[!COOKIES]]), then:
5717-
5718-
<ol>
5719-
<li><p>Let <var>cookies</var> be the result of running the "cookie-string" algorithm (see
5720-
<a href=https://httpwg.org/specs/rfc6265.html#cookie>section 5.4</a> of
5721-
[[!COOKIES]]) with the user agent's cookie store and <var>httpRequest</var>'s
5722-
<a for=request>current URL</a>.
5723-
5724-
<li>If <var>cookies</var> is not the empty string, then <a for="header list">append</a>
5725-
(`<code>Cookie</code>`, <var>cookies</var>) to <var>httpRequest</var>'s
5726-
<a for=request>header list</a>.
5727-
</ol>
5864+
<li><p><a>Append a request `<code>Cookie</code>` header</a> for <var>httpRequest</var>.
57285865

57295866
<li>
57305867
<p>If <var>httpRequest</var>'s <a for=request>header list</a>
@@ -6288,14 +6425,9 @@ optional boolean <var>forceNewConnection</var> (default false), run these steps:
62886425
<li><p>Set <var>response</var>'s <a for=response>body</a> to a new <a for=/>body</a> whose
62896426
<a for=body>stream</a> is <var>stream</var>.
62906427

6291-
<li><p tracking-vector>If <var>includeCredentials</var> is true and the user agent is not
6292-
configured to block cookies for <var>request</var> (see
6293-
<a href=https://httpwg.org/specs/rfc6265.html#privacy-considerations>section 7</a> of
6294-
[[!COOKIES]]), then run the "set-cookie-string" parsing algorithm (see
6295-
<a href=https://httpwg.org/specs/rfc6265.html#set-cookie>section 5.2</a> of [[!COOKIES]]) on the
6296-
<a for=header>value</a> of each <a for=/>header</a> whose <a for=header>name</a> is a
6297-
<a>byte-case-insensitive</a> match for `<code>Set-Cookie</code>` in <var>response</var>'s
6298-
<a for=response>header list</a>, if any, and <var>request</var>'s <a for=request>current URL</a>.
6428+
<li><p tracking-vector>If <var>includeCredentials</var> is true, then the user agent should
6429+
<a>parse and store response `<code>Set-Cookie</code>` headers</a> given <var>request</var> and
6430+
<var>response</var>.
62996431

63006432
<li>
63016433
<p>Run these steps <a>in parallel</a>:

0 commit comments

Comments
 (0)