Skip to content

Commit

Permalink
Bypass credentials check on a per-response basis if Supports-Loading-…
Browse files Browse the repository at this point in the history
…Mode: uncredentialed-prefetch is present. (#242)
  • Loading branch information
jeremyroman authored Jan 23, 2023
1 parent 1903530 commit 9ddcb5c
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 15 deletions.
3 changes: 2 additions & 1 deletion opt-in.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ To resolve this problem, user agents must only preload pages which either:
* Have no stored credentials (for prefetch) or storage of any kind (for prerender); or
* Indicate that they are prepared to perform this sort of upgrade, by sending the appropriate `Supports-Loading-Mode` header value: either `uncredentialed-prefetch`, `uncredentialed-prerender`, or both.

_Note: these values are not currently implemented in Chromium._
> **Note**
> `uncredentialed-prerender` is somewhat speculative at this point; see [cross-site prerendering](prerendering-cross-site.md) for some of the complexity there.
### Cross-origin same-site prerendering

Expand Down
24 changes: 15 additions & 9 deletions prefetch.bs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ spec: COOKIES; urlPrefix: https://httpwg.org/specs/rfc6265.html
type: dfn; text: domain-matches; url: cookie-domain
type: dfn; text: canonicalized host name; url: cookie-domain-canonicalize
type: dfn; text: path-matches; url: cookie-path
spec: nav-speculation; urlPrefix: prerendering.html
type: dfn
text: getting the supported loading modes; url: get-the-supported-loading-modes
text: uncredentialed-prefetch; for: Supports-Loading-Mode; url: supports-loading-mode-uncredentialed-prefetch
</pre>

<h2 id="concepts">Concepts</h2>
Expand Down Expand Up @@ -201,7 +205,7 @@ A <dfn>cross-partition prefetch state</dfn> is a [=struct=] with the following [
* <dfn for="cross-partition prefetch state">isolated partition key</dfn>, a [=network partition key=] whose first item is an [=opaque origin=] and which represents a separate partition in which state can be temporarily stored
* <dfn for="cross-partition prefetch state">origins with conflicting credentials</dfn>, an [=ordered set=] of [=origins=] (initially empty)

<p class="note">Prefetches which start in a different partition as their referrer (e.g., because the URL is cross-site) abort when they would return to that partition (and thus would be credentialed normally), and when an origin for which credentials would have been sent is encountered.</p>
<p class="note">Prefetches which start in a different partition as their referrer (e.g., because the URL is cross-site) abort when they would return to that partition (and thus would be credentialed normally). Unless the response indicates otherwise using [:Supports-Loading-Mode:], a request which would have ordinarily sent credentials but could not due to cross-partition prefetch also causes a prefetch to be abandoned.</p>

A [=prefetch record=]'s <dfn export for="prefetch record">response</dfn> is the [=exchange record/response=] of the last element of its [=prefetch record/redirect chain=], or null if that list [=list/is empty=].

Expand Down Expand Up @@ -478,11 +482,6 @@ A <dfn export>cross-origin prefetch IP anonymization policy</dfn> has an <dfn ex
1. If |request| cannot be fetched given |prefetchRecord|'s [=prefetch record/anonymization policy=] for an [=implementation-defined=] reason, then set |response| to a [=network error=] and [=iteration/break=].

<div class="note">This explicitly acknowledges that implementations might have additional restrictions. For instance, anonymized traffic might not be possible to some hosts, such as those that are not publicly routable and those that have <a href="https://buettner.github.io/private-prefetch-proxy/traffic-advice.html">traffic advice</a> declining private prefetch traffic.
<!-- TODO(jbroman): where do we stash |originsWithConflictingCredentials|? on the prefetch record? -->
1. If |prefetchRecord|'s [=prefetch record/partition state=] is a [=cross-partition prefetch state=]:
1. Let |hypotheticalEnvironment| be the result of [=creating a reserved client=] given |navigable|, |request|'s [=request/current URL=], and null.
1. Let |hypotheticalPartitionKey| be the result of [=determining the network partition key=] given |hypotheticalEnvironment|.
1. If there are [=credentials=] associated with |request|'s [=request/current URL=] and |hypotheticalPartitionKey|, then [=set/append=] |request|'s [=request/current URL=]'s [=url/origin=] to |prefetchRecord|'s [=prefetch record/partition state=]'s [=cross-partition prefetch state/origins with conflicting credentials=].
1. [=redirect chain/Append=] |request| to |prefetchRecord|'s [=prefetch record/redirect chain=].
1. Set |response| to null.
1. If |fetchController| is null, then set |fetchController| to the result of [=fetching=] |request|, with <i>[=fetch/processEarlyHintsResponse=]</i> set to |processEarlyHintsResponse| as defined below, <i>[=fetch/processResponse=]</i> set to |processResponse| as defined below, and <i>[=fetch/useParallelQueue=]</i> set to true.
Expand All @@ -506,7 +505,15 @@ A <dfn export>cross-origin prefetch IP anonymization policy</dfn> has an <dfn ex
1. Set |coopEnforcementResult| to the result of [=enforcing a response's cross-origin opener policy=] given |navigable|'s [=active browsing context=], |request|'s [=request/URL=], |responseOrigin|, |responseCOOP|, |coopEnforcementResult|, and |request|'s [=request/referrer=].
1. If |finalSandboxFlags| is not empty and |responseCOOP|'s [=cross-origin opener policy/value=] is not "`unsafe-none`", then set |response| to an appropriate [=network error=] and [=iteration/break=].
1. If |response| is not a [=network error=], |navigable| is a [=child navigable=], and the result of performing a [=cross-origin resource policy check=] with |navigable|'s [=container document=]'s [=Document/origin=], |navigable|'s [=container document=]'s [=relevant settings object=], |request|'s [=request/destination=], |response|, and true is <strong>blocked</strong>, then set |response| to a [=network error=] and [=iteration/break=].
1. If |prefetchRecord| was given, then [=redirect chain/update the response=] for its [=prefetch record/redirect chain=] given |request| and |response|.
1. If |prefetchRecord| was given, then:
1. [=redirect chain/Update the response=] for its [=prefetch record/redirect chain=] given |request| and |response|.
1. If |prefetchRecord|'s [=prefetch record/partition state=] is a [=cross-partition prefetch state=]:
1. Let |hypotheticalEnvironment| be the result of [=creating a reserved client=] given |navigable|, |currentURL|, and null.
1. Let |hypotheticalPartitionKey| be the result of [=determining the network partition key=] given |hypotheticalEnvironment|.
1. Let |hasConflictingCredentials| be true if there are [=credentials=] associated with |currentURL| and |hypotheticalPartitionKey|, and false otherwise.
1. If |hasConflictingCredentials| is true:
1. Let |loadingModes| be the result of [=getting the supported loading modes=] for |response|.
1. If |loadingModes| does not [=list/contain=] \`<code><a for="Supports-Loading-Mode">uncredentialed-prefetch</a></code>\` then [=set/append=] |currentURL|'s [=url/origin=] to |prefetchRecord|'s [=prefetch record/partition state=]'s [=cross-partition prefetch state/origins with conflicting credentials=].
1. Set |locationURL| to |response|'s [=response/location URL=] given |currentURL|'s [=url/fragment=].
1. If |locationURL| is failure or null, then [=iteration/break=].
1. [=Assert=]: |locationURL| is a [=URL=].
Expand Down Expand Up @@ -618,8 +625,7 @@ The <dfn>list of sufficiently strict speculative navigation referrer policies</d
1. If |navigationParams|'s [=navigation params/response=] does not [=support prefetch=], then set |navigationParams| to null.
1. If |prefetchRecord|'s [=prefetch record/partition state=] is a [=cross-partition prefetch state=] whose [=cross-partition prefetch state/origins with conflicting credentials=] is not [=set/empty=], then set |navigationParams| to null.

<div class="note">This means that if any origin along the redirect chain had credentials, the prefetch is discarded. This reduces the chance of the user observing a logged-out page when they are logged in.</div>
<div class="issue">Update this to include the `` `Supports-Loading-Mode` `` mechanism to allow responses to continue despite cookies.</div>
<div class="note">This means that if any origin along the redirect chain had credentials (and did not override this behavior using [:Supports-Loading-Mode:]), the prefetch is discarded. This reduces the chance of the user observing a logged-out page when they are logged in.</div>
1. [=Queue a global task=] on the [=networking task source=], given |global|, to:
1. If |navigationParams| is not a [=navigation params=], then [=prefetch record/cancel and discard=] |prefetchRecord| given |document| and abort these steps.
1. [=Assert=]: |navigationParams|'s [=navigation params/response=] is the [=exchange record/response=] of |prefetchRecord|'s [=prefetch record/redirect chain=]'s last element.
Expand Down
12 changes: 7 additions & 5 deletions prerendering.bs
Original file line number Diff line number Diff line change
Expand Up @@ -535,17 +535,19 @@ This stores which client hints each origin has opted into receiving, until it ca
1. Otherwise, [=map/set=] [=Accept-CH cache=][|origin|] to |hintSet|.
</div>

<h2 id="supports-loading-mode">The \`<dfn http-header><code>Supports-Loading-Mode</code></dfn>\` HTTP response header</h2>
<h2 id="supports-loading-mode">The \`<dfn export http-header><code>Supports-Loading-Mode</code></dfn>\` HTTP response header</h2>

<em>The following section would be added as a sub-section of [[HTML]]'s <a href="https://html.spec.whatwg.org/multipage/browsers.html#browsers">Loading web pages</a> section.</em>

In some cases, cross-origin web pages might not be prepared to be loaded in a novel context. To allow them to opt in to being loaded in such ways, the \`<a http-header><code>Supports-Loading-Mode</code></a>\` HTTP response header can be used. This header is a [=structured header=]; if present its value must be the single [=structured header/token=] \`<code><a for="Supports-Loading-Mode">credentialed-prerender</a></code>\`.
In some cases, cross-origin web pages might not be prepared to be loaded in a novel context. To allow them to opt in to being loaded in such ways, the \`<a http-header><code>Supports-Loading-Mode</code></a>\` HTTP response header can be used. This header is a [=structured header=]; if present its value must be one or more of the [=structured header/tokens=] listed below.

<p class="note">The parsing is actually done as a [=structured header/list=] of [=structured header/tokens=], and unknown tokens will be ignored. However, authors are best off avoiding any form except the single-token one, for future compatibility.
<p class="note">The parsing is actually done as a [=structured header/list=] of [=structured header/tokens=], and unknown tokens will be ignored.

The \`<code><dfn for="Supports-Loading-Mode">credentialed-prerender</dfn></code>\` token indicates that the response can be used to create a [=prerendering navigable=], despite the prerendering being initiated by a cross-origin same-site referrer. Without this opt-in, such prerenders will fail, as outlined in [[#navigate-fetch-patch]].
The \`<code><dfn export for="Supports-Loading-Mode">credentialed-prerender</dfn></code>\` token indicates that the response can be used to create a [=prerendering navigable=], despite the prerendering being initiated by a cross-origin same-site referrer. Without this opt-in, such prerenders will fail, as outlined in [[#navigate-fetch-patch]].

To <dfn>get the supported loading modes</dfn> for a [=response=] |response|:
The \`<code><dfn export for="Supports-Loading-Mode">uncredentialed-prefetch</dfn></code>\` token indicates that the response is suitable to use even if a top-level navigation to this URL would ordinarily send [=credentials=] such as cookies. For instance, the response may be identical or it may be semantically equivalent (e.g., an HTML resource containing script which can update the document after navigation, when local user state is available).

To <dfn export>get the supported loading modes</dfn> for a [=response=] |response|:

1. If |response| is a [=network error=], then return an empty list.

Expand Down

0 comments on commit 9ddcb5c

Please sign in to comment.