<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Rowan Merewood on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Rowan Merewood</name>
  </author>
  <link href="https://web.dev/authors/rowan_m/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/admin/TASwqsVceW68MrM7bjt8.jpg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Developer Advocate for Chrome and web</subtitle>
  
  
  <entry>
    <title>Migrate to User-Agent Client Hints</title>
    <link href="https://web.dev/migrate-to-ua-ch/"/>
    <updated>2021-05-19T00:00:00Z</updated>
    <id>https://web.dev/migrate-to-ua-ch/</id>
    <content type="html" mode="escaped">&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/User-Agent&quot; rel=&quot;noopener&quot;&gt;User-Agent
string&lt;/a&gt; is
a significant &lt;a href=&quot;https://w3c.github.io/fingerprinting-guidance/#passive&quot; rel=&quot;noopener&quot;&gt;passive fingerprinting
surface&lt;/a&gt; in browsers, as
well as being difficult to process. However, there are all kinds of valid
reasons for collecting and processing user-agent data, so what&#39;s needed is a
path to a better solution. User-Agent Client Hints provide both an explicit way
to declare your need for user-agent data and methods to return the data in an
easy-to-use format.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; For more information on Client Hints and expanding them with user-agent data, read the &lt;a href=&quot;https://web.dev/user-agent-client-hints&quot;&gt;introductory article on User-Agent Client Hints&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;This article will take you through auditing your access to user-agent data and
migrating user-agent string usage to User-Agent Client Hints.&lt;/p&gt;
&lt;h2 id=&quot;audit-collection-and-use-of-user-agent-data&quot;&gt;Audit collection and use of user-agent data &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#audit-collection-and-use-of-user-agent-data&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As with any form of data collection, you should always understand &lt;strong&gt;why&lt;/strong&gt; you
are collecting it. The first step, regardless of whether or not you will be
taking any action, is to understand where and why you are using user-agent data.&lt;/p&gt;
&lt;p&gt;If you don&#39;t know if or where user-agent data is being used, consider searching
your front-end code for use of &lt;code&gt;navigator.userAgent&lt;/code&gt; and your back-end code for
use of the &lt;code&gt;User-Agent&lt;/code&gt; HTTP header. You should also check your front-end code
for use of already deprecated features, such as &lt;code&gt;navigator.platform&lt;/code&gt; and
&lt;code&gt;navigator.appVersion&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From a functional point of view, think about anywhere in your code where you are
recording or processing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Browser name or version&lt;/li&gt;
&lt;li&gt;Operating system name or version&lt;/li&gt;
&lt;li&gt;Device make or model&lt;/li&gt;
&lt;li&gt;CPU type, architecture, or bitness (for example, 64-bit)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&#39;s also likely that you may be using a third-party library or service to
process the user-agent. In this case, check to see if they are updating to
support User-Agent Client Hints.&lt;/p&gt;
&lt;h3 id=&quot;are-you-only-using-basic-user-agent-data&quot;&gt;Are you only using basic user-agent data? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#are-you-only-using-basic-user-agent-data&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The default set of User-Agent Client Hints includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Sec-CH-UA&lt;/code&gt;: browser name and major/significant version&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Sec-CH-UA-Mobile&lt;/code&gt;: boolean value indicating a mobile device&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Sec-CH-UA-Platform&lt;/code&gt;: operating system name
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Note that this has been updated in the spec and will be &lt;a href=&quot;https://groups.google.com/a/chromium.org/g/blink-dev/c/dafizBGwWMw/m/72l-1zm6AAAJ&quot; rel=&quot;noopener&quot;&gt;reflected in
Chrome&lt;/a&gt;
and other Chromium-based browsers shortly.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The reduced version of the user-agent string that is proposed will also retain
this basic information in a backwards-compatible way. For example, instead of
&lt;code&gt;Chrome/90.0.4430.85&lt;/code&gt; the string would include &lt;code&gt;Chrome/90.0.0.0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you are only checking the user-agent string for browser name, major version,
or operating system, then your code will continue to work though you are likely
to see deprecation warnings.&lt;/p&gt;
&lt;p&gt;While you can and should migrate to User-Agent Client Hints, you may have legacy
code or resource constraints that prevent this. The reduction of information in
the user-agent string in this backwards-compatible way is intended to ensure
that while existing code will receive less detailed information, it should still
retain basic functionality.&lt;/p&gt;
&lt;h2 id=&quot;strategy-on-demand-client-side-javascript-api&quot;&gt;Strategy: On-demand client-side JavaScript API &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#strategy-on-demand-client-side-javascript-api&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are currently using &lt;code&gt;navigator.userAgent&lt;/code&gt; you should transition to
preferring &lt;code&gt;navigator.userAgentData&lt;/code&gt; before falling back to parsing the
user-agent string.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userAgentData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// use new hints&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// fall back to user-agent string parsing&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you are checking for mobile or desktop, use the boolean &lt;code&gt;mobile&lt;/code&gt; value:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isMobile &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userAgentData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mobile&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;userAgentData.brands&lt;/code&gt; is an array of objects with &lt;code&gt;brand&lt;/code&gt; and &lt;code&gt;version&lt;/code&gt;
properties where the browser is able to list its compatibility with those
brands. You can access it directly as an array or you may want to use a
&lt;code&gt;some()&lt;/code&gt; call to check if a specific entry is present:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isCompatible&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// In real life you most likely have more complex rules here&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Chromium&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Google Chrome&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;NewBrowser&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;brand&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userAgentData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;brands&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isCompatible&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// browser reports as compatible&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; &lt;code&gt;userAgentData.brands&lt;/code&gt; will contain varying values in a varying order, so don&#39;t rely on something appearing at a certain index. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;If you need one of the more detailed, high-entropy user-agent values, you will
need to specify it and check for the result in the returned &lt;code&gt;Promise&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userAgentData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getHighEntropyValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;model&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;ua&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// requested hints available as attributes&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; model &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ua&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;model&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You may also want to use this strategy if you would like to move from
server-side processing to client-side processing. The JavaScript API does not
require access to HTTP request headers, so user-agent values can be requested at
any point.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Try the &lt;a href=&quot;https://user-agent-client-hints.glitch.me/javascript.html&quot;&gt;User-Agent Client Hints JavaScript API demo&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;strategy-static-server-side-header&quot;&gt;Strategy: Static server-side header &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#strategy-static-server-side-header&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are using the &lt;code&gt;User-Agent&lt;/code&gt; request header on the server and your needs
for that data are relatively consistent across your entire site, then you can
specify the desired client hints as a static set in your responses. This is a
relatively simple approach since you generally only need to configure it in one
location. For example, it may be in your web server configuration if you already
add headers there, your hosting configuration, or top-level configuration of the
framework or platform you use for your site.&lt;/p&gt;
&lt;p&gt;Consider this strategy if you are transforming or customizing the responses
served based on the user-agent data.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; You can also consider migrating to the &lt;a href=&quot;https://web.dev/migrate-to-ua-ch/#strategy-on-demand-client-side-javascript-api&quot;&gt;On-demand client-side JavaScript API&lt;/a&gt; strategy instead of sending additional headers. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Browsers or other clients may choose to supply different default hints, so it&#39;s
good practice to specify everything you need, even if it&#39;s generally provided by
default.&lt;/p&gt;
&lt;p&gt;For example, the current defaults for Chrome would be represented as:&lt;/p&gt;
&lt;p&gt;⬇️ Response headers&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you also wanted to receive the device model in responses, then you would
send:&lt;/p&gt;
&lt;p&gt;⬇️ Response headers&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Ordering is not important, the example is listed alphabetically. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;When processing this on the server-side you should first check if the desired
&lt;code&gt;Sec-CH-UA&lt;/code&gt; header has been sent and then fallback to the &lt;code&gt;User-Agent&lt;/code&gt; header
parsing if it is not available.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Try the &lt;a href=&quot;https://user-agent-client-hints.glitch.me/&quot;&gt;User-Agent Client Hints HTTP header demo&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;strategy-delegating-hints-to-cross-origin-requests&quot;&gt;Strategy: Delegating hints to cross-origin requests &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#strategy-delegating-hints-to-cross-origin-requests&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are requesting cross-origin or cross-site subresources that require
User-Agent Client Hints to be sent on their requests then you will need to
explicitly specify the desired hints using a Permissions Policy.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; &lt;a href=&quot;https://developer.chrome.com/docs/privacy-sandbox/permissions-policy/&quot;&gt;Permissions Policy&lt;/a&gt; is the new form of Feature Policy &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;For example, let&#39;s say that &lt;code&gt;https://blog.site&lt;/code&gt; hosts resources on
&lt;code&gt;https://cdn.site&lt;/code&gt; which can return resources optimized for a specific device.
&lt;code&gt;https://blog.site&lt;/code&gt; can ask for the &lt;code&gt;Sec-CH-UA-Model&lt;/code&gt; hint, but needs to
explicitly delegate it to &lt;code&gt;https://cdn.site&lt;/code&gt; using the &lt;code&gt;Permissions-Policy&lt;/code&gt;
header. The list of policy-controlled hints is available in the &lt;a href=&quot;https://wicg.github.io/client-hints-infrastructure/#policy-controlled-client-hints-features&quot; rel=&quot;noopener&quot;&gt;Clients Hints
Infrastructure
draft&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;⬇️ Response from &lt;code&gt;blog.site&lt;/code&gt; delegating the hint&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Accept-CH: Sec-CH-UA-Model&lt;br /&gt;Permissions-Policy: ch-ua-model=(self &quot;https://cdn.site&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;⬆️ Request to subresources on &lt;code&gt;cdn.site&lt;/code&gt; include the delegated hint&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Sec-CH-UA-Model: &quot;Pixel 5&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You can specify multiple hints for multiple origins, and not just from the &lt;code&gt;ch-ua&lt;/code&gt; range:&lt;/p&gt;
&lt;p&gt;⬇️ Response from &lt;code&gt;blog.site&lt;/code&gt; delegating multiple hints to multiple origins&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Accept-CH: Sec-CH-UA-Model, DPR&lt;br /&gt;Permissions-Policy: ch-ua-model=(self &quot;https://cdn.site&quot;),&lt;br /&gt;                    ch-dpr=(self &quot;https://cdn.site&quot; &quot;https://img.site&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; You do &lt;strong&gt;not&lt;/strong&gt; need to include each delegated hint in &lt;code&gt;Accept-CH&lt;/code&gt;, but you &lt;strong&gt;do&lt;/strong&gt; need to include &lt;code&gt;self&lt;/code&gt; for each hint, even if you are not using it directly at the top-level. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;strategy-delegating-hints-to-iframes&quot;&gt;Strategy: Delegating hints to iframes &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#strategy-delegating-hints-to-iframes&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cross-origin iframes work in a similar way to cross-origin resources, but you
specify the hints you would like to delegate in the &lt;code&gt;allow&lt;/code&gt; attribute.&lt;/p&gt;
&lt;p&gt;⬇️ Response from &lt;code&gt;blog.site&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Accept-CH: Sec-CH-UA-Model&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;↪️ HTML for &lt;code&gt;blog.site&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;iframe&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://widget.site&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;allow&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ch-ua-model&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;iframe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;⬆️ Request to &lt;code&gt;widget.site&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Sec-CH-UA-Model: &quot;Pixel 5&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;allow&lt;/code&gt; attribute in the iframe will override any &lt;code&gt;Accept-CH&lt;/code&gt; header that
&lt;code&gt;widget.site&lt;/code&gt; may send itself, so make sure you&#39;ve specified everything the
iframe&#39;d site will need.&lt;/p&gt;
&lt;h2 id=&quot;strategy-dynamic-server-side-hints&quot;&gt;Strategy: Dynamic server-side hints &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#strategy-dynamic-server-side-hints&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you have specific parts of the user journey where you need a larger selection
of hints than across the rest of the site, you may choose to request those hints
on demand rather than statically across the entire site. This is more complex to
manage, but if you already set different headers on a per route basis it may be
feasible.&lt;/p&gt;
&lt;p&gt;The important thing to remember here is that each instance of the &lt;code&gt;Accept-CH&lt;/code&gt;
header will effectively overwrite the existing set. So, if you are dynamically
setting the header then each page must request the full set of hints required.&lt;/p&gt;
&lt;p&gt;For example, you may have one section on your site where you want to provide
icons and controls that match the user&#39;s operating system. For this, you may
want to additionally pull in &lt;code&gt;Sec-CH-UA-Platform-Version&lt;/code&gt; to serve appropriate
subresources.&lt;/p&gt;
&lt;p&gt;⬇️ Response headers for &lt;code&gt;/blog&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;⬇️ Response headers for &lt;code&gt;/app&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;strategy-server-side-hints-required-on-first-request&quot;&gt;Strategy: Server-side hints required on first request &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#strategy-server-side-hints-required-on-first-request&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There may be cases where you require more than the default set of hints on the
very first request, however this is likely to be rare so make sure you&#39;ve
reviewed the reasoning.&lt;/p&gt;
&lt;p&gt;The first request really means the very first top-level request for that origin
sent in that browsing session. The default set of hints includes the browser
name with major version, the platform, and the mobile indicator. So the question
to ask here is, do you require extended data on the initial page load?&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Also consider making use of the &lt;a href=&quot;https://web.dev/migrate-to-ua-ch/#strategy-on-demand-client-side-javascript-api&quot;&gt;On-demand client-side JavaScript API strategy&lt;/a&gt; to alter content within the page as opposed to server-side. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;For additional hints on the first request there are two options. First, you can
make use of the &lt;code&gt;Critical-CH&lt;/code&gt; header. This takes the same format as &lt;code&gt;Accept-CH&lt;/code&gt;
but tells the browser that it should immediately retry the request if the first
one was sent without the critical hint.&lt;/p&gt;
&lt;p&gt;⬆️ Initial request&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[With default headers]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;⬇️ Response headers&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Accept-CH: Sec-CH-UA-Model&lt;br /&gt;Critical-CH: Sec-CH-UA-Model&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;🔃 Browser retries initial request with the extra header&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[With default headers + …]&lt;br /&gt;Sec-CH-UA-Model: Pixel 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This will incur the overhead of the retry on the very first request, but the
implementation cost is relatively low. Send the extra header and the browser
will do the rest.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Any &lt;code&gt;Critical-CH&lt;/code&gt; values must be a subset of the values in &lt;code&gt;Accept-CH&lt;/code&gt;. &lt;code&gt;Accept-CH&lt;/code&gt; is all the values you would like for the page, &lt;code&gt;Critical-CH&lt;/code&gt; is the subset of those values you &lt;strong&gt;must&lt;/strong&gt; have or you cannot load the page properly. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;For situations where you require really do require additional hints on the very
first page load, the &lt;a href=&quot;https://github.com/WICG/client-hints-infrastructure/blob/main/reliability.md#connection-level-settings&quot; rel=&quot;noopener&quot;&gt;Client Hints Reliability
proposal&lt;/a&gt;
is laying out a route to specify hints in the connection-level settings. This
makes use of the &lt;a href=&quot;https://tools.ietf.org/html/draft-vvv-tls-alps&quot; rel=&quot;noopener&quot;&gt;Application-Layer Protocol
Settings(ALPS)&lt;/a&gt; extension to TLS
1.3 to enable this early passing of hints on HTTP/2 and HTTP/3 connections. This
is still at a very early stage, but if you actively manage your own TLS and
connection settings then this is an ideal time to contribute.&lt;/p&gt;
&lt;h2 id=&quot;strategy-legacy-support&quot;&gt;Strategy: Legacy support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#strategy-legacy-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You may have legacy or third-party code on your site that depends on
&lt;code&gt;navigator.userAgent&lt;/code&gt;, including portions of the user-agent string that will be
reduced. Long-term you should plan to move to the equivalent
&lt;code&gt;navigator.userAgentData&lt;/code&gt; calls, but there is an interim solution.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; This is not recommended and not supported in any way. This solution is included for completeness but if you spend any time attempting to fix bugs in it, that time would be better spent doing the actual migration. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/GoogleChromeLabs/uach-retrofill&quot; rel=&quot;noopener&quot;&gt;UA-CH retrofill&lt;/a&gt; is a small
library that allows you to overwrite &lt;code&gt;navigator.userAgent&lt;/code&gt; with a new string
built from the requested &lt;code&gt;navigator.userAgentData&lt;/code&gt; values.&lt;/p&gt;
&lt;p&gt;For example, this code will generate a user-agent string that additionally
includes the &amp;quot;model&amp;quot; hint:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; overrideUserAgentUsingClientHints &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./uach-retrofill.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;overrideUserAgentUsingClientHints&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;model&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userAgent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The resulting string would show the &lt;code&gt;Pixel 5&lt;/code&gt; model, but still shows the reduced
&lt;code&gt;92.0.0.0&lt;/code&gt; as the &lt;code&gt;uaFullVersion&lt;/code&gt; hint was not requested:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Mozilla/5.0 (Linux; Android 10.0; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.0.0 Mobile Safari/537.36&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;further-support&quot;&gt;Further support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/migrate-to-ua-ch/#further-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If these strategies do not cover your use case, please start a &lt;a href=&quot;https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/discussions&quot; rel=&quot;noopener&quot;&gt;Discussion in
privacy-sandbox-dev-support
repo&lt;/a&gt;
and we can explore your issue together.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rcrazy?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Ricardo
Rocha&lt;/a&gt;
on &lt;a href=&quot;https://unsplash.com/photos/nj1bqRzClq8&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content>
    <author>
      <name>Rowan Merewood</name>
    </author>
  </entry>
  
  <entry>
    <title>Schemeful Same-Site</title>
    <link href="https://web.dev/schemeful-samesite/"/>
    <updated>2020-11-20T00:00:00Z</updated>
    <id>https://web.dev/schemeful-samesite/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This article is part of a series on the &lt;code&gt;SameSite&lt;/code&gt; cookie attribute changes that includes:  &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/understanding-cookies/&quot;&gt;Understanding cookies&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/samesite-cookies-explained/&quot;&gt;SameSite cookies explained&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/samesite-cookie-recipes/&quot;&gt;SameSite cookies recipes&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;&lt;a href=&quot;https://mikewest.github.io/cookie-incrementalism/draft-west-cookie-incrementalism.html#rfc.section.3.3&quot; rel=&quot;noopener&quot;&gt;Schemeful
Same-Site&lt;/a&gt;
modifies the definition of a (web)site from just the registrable domain to the
scheme + registrable domain. You can find more details and examples in
&lt;a href=&quot;https://web.dev/same-site-same-origin/#%22schemeful-same-site%22&quot;&gt;Understanding &amp;quot;same-site&amp;quot; and
&amp;quot;same-origin&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;aside class=&quot;aside flow color-secondary-box-text bg-secondary-box-bg&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Highlighter pen&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M10.22 9.49l-5.91 6c-.77.8-.7 2.05.08 2.85L.77 22h5.68l.74-.75c.78.81 1.95.86 2.73.05l5.96-6.05-5.66-5.76zm12.46-4l-2.82-2.87c-.78-.8-2.07-.84-2.84-.04l-5.75 5.85 5.66 5.75 5.69-5.78c.77-.81.83-2.11.06-2.91z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Key Term&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; This means that the insecure HTTP version of a site, for example, &lt;strong&gt;http&lt;/strong&gt;://website.example, and the secure HTTPS version of that site, &lt;strong&gt;https&lt;/strong&gt;://website.example, are now considered &lt;strong&gt;cross-site&lt;/strong&gt; to each other. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The good news is: if your website is already fully upgraded to HTTPS then you
don&#39;t need to worry about anything. Nothing will change for you.&lt;/p&gt;
&lt;p&gt;If you haven&#39;t fully upgraded your website yet then this should be the priority.
However, if there are cases where your site visitors will go between HTTP and
HTTPS then some of those common scenarios and the associated &lt;code&gt;SameSite&lt;/code&gt; cookie
behavior are outlined below.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; The long-term plan is to &lt;a href=&quot;https://blog.chromium.org/2020/10/progress-on-privacy-sandbox-and.html&quot;&gt;phase out support for third-party cookies entirely&lt;/a&gt;, replacing them with privacy preserving alternatives. Setting &lt;code&gt;SameSite=None; Secure&lt;/code&gt; on a cookie to allow it to be sent across schemes should only be considered a temporary solution in the migration towards full HTTPS. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;You can enable these changes for testing in both Chrome and Firefox.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;From Chrome 86, enable &lt;code&gt;about://flags/#schemeful-same-site&lt;/code&gt;. Track progress
on the &lt;a href=&quot;https://chromestatus.com/feature/5096179480133632&quot; rel=&quot;noopener&quot;&gt;Chrome Status
page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;From Firefox 79, set &lt;code&gt;network.cookie.sameSite.schemeful&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; via
&lt;code&gt;about:config&lt;/code&gt;. Track progress via &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1651119&quot; rel=&quot;noopener&quot;&gt;the Bugzilla
issue&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One of the main reasons for the change to &lt;code&gt;SameSite=Lax&lt;/code&gt; as the default for
cookies was to protect against &lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/CSRF&quot; rel=&quot;noopener&quot;&gt;Cross-Site Request Forgery
(CSRF)&lt;/a&gt;. However,
insecure HTTP traffic still presents an opportunity for network attackers to
tamper with cookies that will then be used on the secure HTTPS version of the
site. Creating this additional cross-site boundary between schemes provides
further defense against these attacks.&lt;/p&gt;
&lt;h2 id=&quot;common-cross-scheme-scenarios&quot;&gt;Common cross-scheme scenarios &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#common-cross-scheme-scenarios&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;aside class=&quot;aside flow color-secondary-box-text bg-secondary-box-bg&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Highlighter pen&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M10.22 9.49l-5.91 6c-.77.8-.7 2.05.08 2.85L.77 22h5.68l.74-.75c.78.81 1.95.86 2.73.05l5.96-6.05-5.66-5.76zm12.46-4l-2.82-2.87c-.78-.8-2.07-.84-2.84-.04l-5.75 5.85 5.66 5.75 5.69-5.78c.77-.81.83-2.11.06-2.91z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Key Term&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; In the examples below where the URLs all have the same registrable domain, e.g. site.example, but different schemes, for example, &lt;strong&gt;http&lt;/strong&gt;://site.example vs. &lt;strong&gt;https&lt;/strong&gt;://site.example, they are referred to as &lt;strong&gt;cross-scheme&lt;/strong&gt; to each other. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;navigation&quot;&gt;Navigation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#navigation&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Navigating between cross-scheme versions of a website (for example, linking from
&lt;strong&gt;http&lt;/strong&gt;://site.example to &lt;strong&gt;https&lt;/strong&gt;://site.example) would previously allow
&lt;code&gt;SameSite=Strict&lt;/code&gt; cookies to be sent. This is now treated as a cross-site
navigation which means &lt;code&gt;SameSite=Strict&lt;/code&gt; cookies will be blocked.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A cross-scheme navigation triggered by following a link on the insecure HTTP version of a site to the secure HTTPS version. SameSite=Strict cookies blocked, SameSite=Lax and SameSite=None; Secure cookies are allowed.&quot; decoding=&quot;async&quot; height=&quot;342&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yDViqKg9eeEeAEiCNqe4.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Cross-scheme navigation from HTTP to HTTPS.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;table&gt;
  &lt;tr&gt;
   &lt;td&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;strong&gt;HTTP → HTTPS&lt;/strong&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;strong&gt;HTTPS → HTTP&lt;/strong&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;code&gt;SameSite=Strict&lt;/code&gt;
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;code&gt;SameSite=Lax&lt;/code&gt;
   &lt;/td&gt;
   &lt;td&gt;✓ Allowed
   &lt;/td&gt;
   &lt;td&gt;✓ Allowed
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;code&gt;SameSite=None;Secure&lt;/code&gt;
   &lt;/td&gt;
   &lt;td&gt;✓ Allowed
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;h3 id=&quot;loading-subresources&quot;&gt;Loading subresources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#loading-subresources&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; All major browsers block &lt;a href=&quot;https://developer.mozilla.org/docs/Web/Security/Mixed_content&quot;&gt;active mixed content&lt;/a&gt; such as scripts or iframes. Additionally, browsers including &lt;a href=&quot;https://blog.chromium.org/2019/10/no-more-mixed-messages-about-https.html&quot;&gt;Chrome&lt;/a&gt; and &lt;a href=&quot;https://groups.google.com/g/mozilla.dev.platform/c/F163Jz32oYY&quot;&gt;Firefox&lt;/a&gt; are working toward upgrading or blocking passive mixed content. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Any changes you make here should only be considered a temporary fix while you
work to upgrade to full HTTPS.&lt;/p&gt;
&lt;p&gt;Examples of subresources include images, iframes, and network requests made with
XHR or Fetch.&lt;/p&gt;
&lt;p&gt;Loading a cross-scheme subresource on a page would previously allow
&lt;code&gt;SameSite=Strict&lt;/code&gt; or &lt;code&gt;SameSite=Lax&lt;/code&gt; cookies to be sent or set. Now this is
treated the same way as any other third-party or cross-site subresource which
means that any &lt;code&gt;SameSite=Strict&lt;/code&gt; or &lt;code&gt;SameSite=Lax&lt;/code&gt; cookies will be blocked.&lt;/p&gt;
&lt;p&gt;Additionally, even if the browser does allow resources from insecure schemes to
be loaded on a secure page, all cookies will be blocked on these requests as
third-party or cross-site cookies require &lt;code&gt;Secure&lt;/code&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A cross-scheme subresource resulting from a resource from the secure HTTPS version of the site being included on the insecure HTTP version. SameSite=Strict and SameSite=Lax cookies blocked, and SameSite=None; Secure cookies are allowed.&quot; decoding=&quot;async&quot; height=&quot;285&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GgR6Yln1f9JGkt04exRC.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    An HTTP page including a cross-scheme subresource via HTTPS.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;table&gt;
  &lt;tr&gt;
   &lt;td&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;strong&gt;HTTP → HTTPS&lt;/strong&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;strong&gt;HTTPS → HTTP&lt;/strong&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;code&gt;SameSite=Strict&lt;/code&gt;
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;code&gt;SameSite=Lax&lt;/code&gt;
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;code&gt;SameSite=None;Secure&lt;/code&gt;
   &lt;/td&gt;
   &lt;td&gt;✓ Allowed
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;h3 id=&quot;posting-a-form&quot;&gt;POSTing a form &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#posting-a-form&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Posting between cross-scheme versions of a website would previously allow
cookies set with &lt;code&gt;SameSite=Lax&lt;/code&gt; or &lt;code&gt;SameSite=Strict&lt;/code&gt; to be sent. Now this is
treated as a cross-site POST—only &lt;code&gt;SameSite=None&lt;/code&gt; cookies can be sent. You may
encounter this scenario on sites that present the insecure version by default,
but upgrade users to the secure version on submission of the sign-in or
check-out form.&lt;/p&gt;
&lt;p&gt;As with subresources, if the request is going from a secure, e.g. HTTPS, to an
insecure, e.g. HTTP, context then all cookies will be blocked on these requests
as third-party or cross-site cookies require &lt;code&gt;Secure&lt;/code&gt;.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; The best solution here is to ensure both the form page and destination are on a secure connection such as HTTPS. This is especially important if the user is entering any sensitive information into the form. &lt;/div&gt;&lt;/aside&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A cross-scheme form submission resulting from a form on the insecure HTTP version of the site being submitted to the secure HTTPS version. SameSite=Strict and SameSite=Lax cookies blocked, and SameSite=None; Secure cookies are allowed.&quot; decoding=&quot;async&quot; height=&quot;376&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ud9LkDeGJUWHObifD718.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Cross-scheme form submission from HTTP to HTTPS.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;table&gt;
  &lt;tr&gt;
   &lt;td&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;strong&gt;HTTP → HTTPS&lt;/strong&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;strong&gt;HTTPS → HTTP&lt;/strong&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;code&gt;SameSite=Strict&lt;/code&gt;
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;code&gt;SameSite=Lax&lt;/code&gt;
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;code&gt;SameSite=None;Secure&lt;/code&gt;
   &lt;/td&gt;
   &lt;td&gt;✓ Allowed
   &lt;/td&gt;
   &lt;td&gt;⛔ Blocked
   &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;h2 id=&quot;how-can-i-test-my-site&quot;&gt;How can I test my site? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#how-can-i-test-my-site&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Developer tooling and messaging are available in Chrome and Firefox.&lt;/p&gt;
&lt;p&gt;From Chrome 86, the &lt;a href=&quot;https://developer.chrome.com/docs/devtools/issues/&quot; rel=&quot;noopener&quot;&gt;Issue tab in
DevTools&lt;/a&gt; will
include Schemeful Same-Site issues. You may see the following issues highlighted
for your site.&lt;/p&gt;
&lt;p&gt;Navigation issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;Migrate entirely to HTTPS to continue having cookies sent on same-site
requests&amp;quot;—A warning that the cookie &lt;strong&gt;will be&lt;/strong&gt; blocked in a future version
of Chrome.&lt;/li&gt;
&lt;li&gt;&amp;quot;Migrate entirely to HTTPS to have cookies sent on same-site requests&amp;quot;—A
warning that the cookie &lt;strong&gt;has been&lt;/strong&gt; blocked.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Subresource loading issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;Migrate entirely to HTTPS to continue having cookies sent to same-site
subresources&amp;quot; or &amp;quot;Migrate entirely to HTTPS to continue allowing cookies to
be set by same-site subresources&amp;quot;—Warnings that the cookie &lt;strong&gt;will be&lt;/strong&gt;
blocked in a future version of Chrome.&lt;/li&gt;
&lt;li&gt;&amp;quot;Migrate entirely to HTTPS to have cookies sent to same-site subresources&amp;quot;
or &amp;quot;Migrate entirely to HTTPS to allow cookies to be set by same-site
subresources&amp;quot;—Warnings that the cookie &lt;strong&gt;has been&lt;/strong&gt; blocked. The latter
warning can also appear when POSTing a form.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More detail is available in &lt;a href=&quot;https://www.chromium.org/updates/schemeful-same-site/testing-and-debugging-tips-for-schemeful-same-site&quot; rel=&quot;noopener&quot;&gt;Testing and Debugging Tips for Schemeful
Same-Site&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From Firefox 79, with &lt;code&gt;network.cookie.sameSite.schemeful&lt;/code&gt; set to &lt;code&gt;true&lt;/code&gt; via
&lt;code&gt;about:config&lt;/code&gt; the console will display message for Schemeful Same-Site issues.
You may see the following on your site:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;Cookie &lt;code&gt;cookie_name&lt;/code&gt; &lt;strong&gt;will be soon&lt;/strong&gt; treated as cross-site cookie against
&lt;code&gt;http://site.example/&lt;/code&gt; because the scheme does not match.&amp;quot;&lt;/li&gt;
&lt;li&gt;&amp;quot;Cookie &lt;code&gt;cookie_name&lt;/code&gt; &lt;strong&gt;has been&lt;/strong&gt; treated as cross-site against
&lt;code&gt;http://site.example/&lt;/code&gt; because the scheme does not match.&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;faq&quot;&gt;FAQ &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#faq&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;my-site-is-already-fully-available-on-https,-why-am-i-seeing-issues-in-my-browsers-devtools&quot;&gt;My site is already fully available on HTTPS, why am I seeing issues in my browser&#39;s DevTools? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#my-site-is-already-fully-available-on-https,-why-am-i-seeing-issues-in-my-browsers-devtools&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It&#39;s possible that some of your links and subresources still point to insecure
URLs.&lt;/p&gt;
&lt;p&gt;One way to fix this issue is to use &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Strict-Transport-Security&quot; rel=&quot;noopener&quot;&gt;HTTP
Strict-Transport-Security&lt;/a&gt;
(HSTS) and the &lt;code&gt;includeSubDomain&lt;/code&gt; directive. With HSTS + &lt;code&gt;includeSubDomain&lt;/code&gt; even
if one of your pages accidentally includes an insecure link the browser will
automatically use the secure version instead.&lt;/p&gt;
&lt;h3 id=&quot;what-if-i-cant-upgrade-to-https&quot;&gt;What if I can&#39;t upgrade to HTTPS? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#what-if-i-cant-upgrade-to-https&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While we strongly recommend that you upgrade your site entirely to HTTPS to
protect your users, if you&#39;re unable to do so yourself we suggest speaking with
your hosting provider to see if they can offer that option. If you self-host,
then &lt;a href=&quot;https://letsencrypt.org/&quot; rel=&quot;noopener&quot;&gt;Let&#39;s Encrypt&lt;/a&gt; provides a number of tools to
install and configure a certificate. You can also investigate moving your site
behind a CDN or other proxy that can provide the HTTPS connection.&lt;/p&gt;
&lt;p&gt;If that&#39;s still not possible then try relaxing the &lt;code&gt;SameSite&lt;/code&gt; protection on
affected cookies.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In cases where only &lt;code&gt;SameSite=Strict&lt;/code&gt; cookies are being blocked you can lower
the protection to &lt;code&gt;Lax&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In cases where both &lt;code&gt;Strict&lt;/code&gt; and &lt;code&gt;Lax&lt;/code&gt; cookies are being blocked and your
cookies are being sent to (or set from) a secure URL you can lower the
protections to &lt;code&gt;None&lt;/code&gt;.
&lt;ul&gt;
&lt;li&gt;This workaround will &lt;strong&gt;fail&lt;/strong&gt; if the URL you&#39;re sending cookies to (or
setting them from) is insecure. This is because &lt;code&gt;SameSite=None&lt;/code&gt; requires the
&lt;code&gt;Secure&lt;/code&gt; attribute on cookies which means those cookies may not be sent or
set over an insecure connection. In this case you will be unable to access
that cookie until your site is upgraded to HTTPS.&lt;/li&gt;
&lt;li&gt;Remember, this is only temporary as eventually third-party cookies will be
phased out entirely.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-does-this-affect-my-cookies-if-i-havent-specified-a-samesite-attribute&quot;&gt;How does this affect my cookies if I haven&#39;t specified a &lt;code&gt;SameSite&lt;/code&gt; attribute? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#how-does-this-affect-my-cookies-if-i-havent-specified-a-samesite-attribute&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Cookies without a &lt;code&gt;SameSite&lt;/code&gt; attribute are treated as if they specified
&lt;code&gt;SameSite=Lax&lt;/code&gt; and the same cross-scheme behavior applies to these cookies as
well. Note that the temporary exception to unsafe methods still applies, see
&lt;a href=&quot;https://www.chromium.org/updates/same-site/faq&quot; rel=&quot;noopener&quot;&gt;the Lax + POST mitigation in the Chromium &lt;code&gt;SameSite&lt;/code&gt;
FAQ&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h3 id=&quot;how-are-websockets-affected&quot;&gt;How are WebSockets affected? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/schemeful-samesite/#how-are-websockets-affected&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;WebSocket connections will still be considered same-site if they&#39;re the same
secureness as the page.&lt;/p&gt;
&lt;p&gt;Same-site:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wss://&lt;/code&gt; connection from &lt;code&gt;https://&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ws://&lt;/code&gt; connection from &lt;code&gt;http://&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cross-site:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wss://&lt;/code&gt; connection from &lt;code&gt;http://&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ws://&lt;/code&gt; connection from &lt;code&gt;https://&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/wNjgWrEXAL0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Julissa
Capdevilla&lt;/a&gt;
on
&lt;a href=&quot;https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content>
    <author>
      <name>Steven Bingler</name>
    </author><author>
      <name>Rowan Merewood</name>
    </author>
  </entry>
  
  <entry>
    <title>Understanding cookies</title>
    <link href="https://web.dev/understanding-cookies/"/>
    <updated>2019-10-30T00:00:00Z</updated>
    <id>https://web.dev/understanding-cookies/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This article is part of a series on the &lt;code&gt;SameSite&lt;/code&gt; cookie attribute changes that includes:  &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/samesite-cookies-explained/&quot;&gt;SameSite cookies explained&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/samesite-cookie-recipes/&quot;&gt;SameSite cookies recipes&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/schemeful-samesite/&quot;&gt;Schemeful Same-Site&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;A cookie is a small file that websites store on their users’ machine, the information it stores travels back and forth between the browser and the website.&lt;/p&gt;
&lt;p&gt;Each cookie is a key-value pair along with a number of attributes that control when and where that cookie is used. These attributes are used to set things like expiration dates or indicating the cookie should only be sent over HTTPS. You can set a cookie in an HTTP header or through JavaScript interface.&lt;/p&gt;
&lt;p&gt;Cookies are one of the methods available for adding persistent state to web sites. Over the years their capabilities have grown and evolved, but left the platform with some problematic legacy issues. To address this, browsers (including Chrome, Firefox, and Edge) are changing their behavior to enforce more privacy-preserving defaults.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Learn more about &lt;a href=&quot;https://developer.chrome.com/docs/privacy-sandbox/&quot;&gt;Chrome’s effort to protect people&#39;s privacy online&lt;/a&gt; and give companies and developers tools to build thriving digital businesses. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;cookies-in-action&quot;&gt;Cookies in action &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-cookies/#cookies-in-action&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Say you have a blog where you want to display a &amp;quot;What&#39;s new&amp;quot; promo to your
users. Users can dismiss the promo and then they won&#39;t see it again for a while.
You can store that preference in a cookie, set it to expire in a month
(2,600,000 seconds), and only send it over HTTPS. That header would look like
this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Cookie: promo_shown=1; Max-Age=2600000; Secure&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figure&gt;
  &lt;img alt=&quot;Three cookies being sent to a browser from a server in a response&quot; decoding=&quot;async&quot; height=&quot;276&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/jJ1fqcsAk9Ig3hManFBO.png?auto=format&amp;w=1600 1600w&quot; style=&quot;max-width: 35vw&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Servers set cookies using the &lt;code&gt;Set-Cookie&lt;/code&gt; header.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;When your reader views a page that meets those requirements—they&#39;re on a
secure connection and the cookie is less than a month old—their browser
will send this header in its request:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Cookie: promo_shown=1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figure&gt;
  &lt;img alt=&quot;Three cookies being sent from a browser to a server in a request&quot; decoding=&quot;async&quot; height=&quot;165&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rq21WQpOZFvfgS9bbjmc.png?auto=format&amp;w=1600 1600w&quot; style=&quot;max-width: 35vw&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Your browser sends cookies back in the &lt;code&gt;Cookie&lt;/code&gt; header.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You can also add and read the cookies available to that site in JavaScript using
&lt;code&gt;document.cookie&lt;/code&gt;. Making an assignment to &lt;code&gt;document.cookie&lt;/code&gt; will create or
override a cookie with that key. For example, you can try the following in your
browser&#39;s JavaScript console:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;→ document.cookie = &quot;promo_shown=1; Max-Age=2600000; Secure&quot;&lt;br /&gt;← &quot;promo_shown=1; Max-Age=2600000; Secure&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Reading &lt;code&gt;document.cookie&lt;/code&gt; will output all the cookies accessible in the current
context, with each cookie separated by a semicolon:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;→ document.cookie;&lt;br /&gt;← &quot;promo_shown=1; color_theme=peachpuff; sidebar_loc=left&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figure&gt;
  &lt;img alt=&quot;JavaScript accessing cookies within the browser&quot; decoding=&quot;async&quot; height=&quot;382&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 600px) 600px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mbV00Gy5VAPTUls0i7cM.png?auto=format&amp;w=1200 1200w&quot; style=&quot;max-width: 35vw&quot; width=&quot;600&quot; /&gt;
  &lt;figcaption&gt;
    JavaScript can access cookies using &lt;code&gt;document.cookie&lt;/code&gt;.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If you try this on a selection of popular sites you will notice that most of
them set significantly more than just three cookies. In most cases, those
cookies are sent on every single request to that domain, which has a number of
implications. Upload bandwidth is often more restricted than download for your
users, so that overhead on all outbound requests is adding a delay on your time
to first byte. Be conservative in the number and size of cookies you set. Make
use of the &lt;code&gt;Max-Age&lt;/code&gt; attribute to help ensure that cookies don&#39;t hang around
longer than needed.&lt;/p&gt;
&lt;h2 id=&quot;what-are-first-party-and-third-party-cookies&quot;&gt;What are first-party and third-party cookies? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-cookies/#what-are-first-party-and-third-party-cookies&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you go back to that same selection of sites you were looking at before, you
probably noticed that there were cookies present for a variety of domains, not
just the one you were currently visiting. Cookies that match the domain of the
current site, that is, what&#39;s displayed in the browser&#39;s address bar, are referred
to as &lt;strong&gt;first-party&lt;/strong&gt; cookies. Similarly, cookies from domains other than the
current site are referred to as &lt;strong&gt;third-party&lt;/strong&gt; cookies. This isn&#39;t an absolute
label but is relative to the user&#39;s context; the same cookie can be either
first-party or third-party depending on which site the user is on at the time.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Three cookies being sent to a browser from different requests on the same page&quot; decoding=&quot;async&quot; height=&quot;346&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zjXpDz2jAdXMT83Nm3IT.png?auto=format&amp;w=1600 1600w&quot; style=&quot;max-width: 35vw&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Cookies may come from a variety of different domains on one page.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Continuing the example from above, let&#39;s say one of your blog posts has a
picture of a particularly amazing cat in it and it&#39;s hosted at
&lt;code&gt;/blog/img/amazing-cat.png&lt;/code&gt;. Because it&#39;s such an amazing image, another person
uses it directly on their site. If a visitor has been to your blog and has the
&lt;code&gt;promo_shown&lt;/code&gt; cookie, then when they view &lt;code&gt;amazing-cat.png&lt;/code&gt; on the other
person&#39;s site that cookie &lt;strong&gt;will be sent&lt;/strong&gt; in that request for the image. This
isn&#39;t particularly useful for anyone since &lt;code&gt;promo_shown&lt;/code&gt; isn&#39;t used for anything
on this other person&#39;s site, it&#39;s just adding overhead to the request.&lt;/p&gt;
&lt;p&gt;If that&#39;s an unintended effect, why would you want to do this? It&#39;s this
mechanism that allows sites to maintain state when they are being used in a
third-party context. For example, if you embed a YouTube video on your site then
visitors will see a &amp;quot;Watch later&amp;quot; option in the player. If your visitor is
already signed in to YouTube, that session is being made available in the
embedded player by a third-party cookie—meaning that &amp;quot;Watch later&amp;quot; button will
just save the video in one go rather than prompting them to sign in or having to
navigate them away from your page and back over to YouTube.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;The same cookie being sent in three different contexts&quot; decoding=&quot;async&quot; height=&quot;433&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/u9chHBLm3i27yFRwHx5W.png?auto=format&amp;w=1600 1600w&quot; style=&quot;max-width: 35vw&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    A cookie in a third-party context is sent when visiting different pages.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;One of the cultural properties of the web is that it&#39;s tended to be open by
default. This is part of what has made it possible for so many people to create
their own content and apps there. However, this has also brought a number of
security and privacy concerns. Cross-site request forgery (CSRF) attacks rely on
the fact that cookies are attached to any request to a given origin, no matter
who initiates the request. For example, if you visit &lt;code&gt;evil.example&lt;/code&gt; then it can
trigger requests to &lt;code&gt;your-blog.example&lt;/code&gt;, and your browser will happily attach
the associated cookies. If your blog isn&#39;t careful with how it validates those
requests then &lt;code&gt;evil.example&lt;/code&gt; could trigger actions like deleting posts or adding
their own content.&lt;/p&gt;
&lt;p&gt;Users are also becoming more aware of how cookies can be used to track their
activity across multiple sites. However until now there hasn&#39;t been a way to
explicitly state your intent with the cookie. Your &lt;code&gt;promo_shown&lt;/code&gt; cookie should
only be sent in a first-party context, whereas a session cookie for a widget
meant to be embedded on other sites is intentionally there for providing the
signed-in state in a third-party context.&lt;/p&gt;
&lt;p&gt;You can explicitly state your intent with a cookie by setting the appropriate &lt;a href=&quot;https://web.dev/samesite-cookies-explained&quot;&gt;SameSite attribute&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To identify your first-party cookies and set appropriate attributes, check out &lt;a href=&quot;https://web.dev/first-party-cookie-recipes/&quot;&gt;First-party cookie recipes&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Rowan Merewood</name>
    </author>
  </entry>
  
  <entry>
    <title>SameSite cookie recipes</title>
    <link href="https://web.dev/samesite-cookie-recipes/"/>
    <updated>2019-10-30T00:00:00Z</updated>
    <id>https://web.dev/samesite-cookie-recipes/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This article is part of a series on the &lt;code&gt;SameSite&lt;/code&gt; cookie attribute changes that includes:  &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/understanding-cookies/&quot;&gt;Understanding cookies&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/samesite-cookies-explained/&quot;&gt;SameSite cookies explained&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/schemeful-samesite/&quot;&gt;Schemeful Same-Site&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;&lt;a href=&quot;https://www.chromium.org/updates/same-site&quot; rel=&quot;noopener&quot;&gt;Chrome&lt;/a&gt;,
&lt;a href=&quot;https://groups.google.com/d/msg/mozilla.dev.platform/nx2uP0CzA9k/BNVPWDHsAQAJ&quot; rel=&quot;noopener&quot;&gt;Firefox&lt;/a&gt;,
&lt;a href=&quot;https://groups.google.com/a/chromium.org/d/msg/blink-dev/AknSSyQTGYs/8lMmI5DwEAAJ&quot; rel=&quot;noopener&quot;&gt;Edge&lt;/a&gt;,
and others will be changing their default behavior in line with the IETF
proposal,
&lt;a href=&quot;https://tools.ietf.org/html/draft-west-cookie-incrementalism-00&quot; rel=&quot;noopener&quot;&gt;Incrementally Better Cookies&lt;/a&gt;
so that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cookies without a &lt;code&gt;SameSite&lt;/code&gt; attribute will be treated as &lt;code&gt;SameSite=Lax&lt;/code&gt;,
meaning the default behavior will be to restrict cookies to first party
contexts &lt;strong&gt;only&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Cookies for cross-site usage &lt;strong&gt;must&lt;/strong&gt; specify &lt;code&gt;SameSite=None; Secure&lt;/code&gt; to
enable inclusion in third party context.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This feature is the &lt;a href=&quot;https://blog.chromium.org/2020/05/resuming-samesite-cookie-changes-in-july.html&quot; rel=&quot;noopener&quot;&gt;default behavior from Chrome 84 stable
onward&lt;/a&gt;.
If you have not already done so, you should update the attributes for your
third-party cookies so they will not be blocked in the future.&lt;/p&gt;
&lt;h2 id=&quot;cross-browser-support&quot;&gt;Cross-browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#cross-browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;See the
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie#Browser_compatibility&quot; rel=&quot;noopener&quot;&gt;Browser compatibility&lt;/a&gt;
section of MDN&#39;s &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Set-Cookie&lt;/code&gt;&lt;/a&gt;
page.&lt;/p&gt;
&lt;h2 id=&quot;use-cases-for-cross-site-or-third-party-cookies&quot;&gt;Use cases for cross-site or third-party cookies &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#use-cases-for-cross-site-or-third-party-cookies&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are a number of common use cases and patterns where cookies need to be
sent in a third-party context. If you provide or depend on one of these use
cases, ensure that either you or the provider are updating their cookies to
ensure the service continues to function correctly.&lt;/p&gt;
&lt;h3 id=&quot;content-within-an-lessiframegreater&quot;&gt;Content within an &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#content-within-an-lessiframegreater&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Content from a different site displayed in an &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; is in a third-party
context. Standard use cases here are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Embedded content shared from other sites, such as videos, maps, code samples,
and social posts.&lt;/li&gt;
&lt;li&gt;Widgets from external services such as payments, calendars, booking, and
reservation functionality.&lt;/li&gt;
&lt;li&gt;Widgets such as social buttons or anti-fraud services that create less obvious
&lt;code&gt;&amp;lt;iframes&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cookies may be used here to, among other things, maintain session state, store
general preferences, enable statistics, or personalize content for users with
existing accounts.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Diagram of a browser window where the URL of embedded content does not match the URL of the page.&quot; decoding=&quot;async&quot; height=&quot;383&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 468px) 468px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fTUQP4SffHHcexSipvlz.png?auto=format&amp;w=936 936w&quot; style=&quot;max-width: 35vw;&quot; width=&quot;468&quot; /&gt;
  &lt;figcaption&gt;
    If the embedded content doesn&#39;t come from the same site as the top-level
    browsing context, it&#39;s third-party content.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Additionally, as the web is inherently composable, &lt;code&gt;&amp;lt;iframes&amp;gt;&lt;/code&gt; are used to embed
content that is also viewed in a top-level or first-party context. Any cookies
used by that site will be considered as third-party cookies when the site is
displayed within the frame. If you&#39;re creating sites that you intend to be
easily embedded by others while also relying on cookies to function, you will
also need to ensure those are marked for cross-site usage or that you can
gracefully fallback without them.&lt;/p&gt;
&lt;h3 id=&quot;unsafe-requests-across-sites&quot;&gt;&amp;quot;Unsafe&amp;quot; requests across sites &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#unsafe-requests-across-sites&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While &amp;quot;unsafe&amp;quot; may sound slightly concerning here, this refers to any request
that may be intended to change state. On the web that&#39;s primarily POST requests.
Cookies marked as &lt;code&gt;SameSite=Lax&lt;/code&gt; will be sent on safe top-level navigations,
e.g. clicking a link to go to a different site. However something like a
&lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; submission via POST to a different site would not include cookies.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Diagram of a request moving from one page to another.&quot; decoding=&quot;async&quot; height=&quot;382&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 719px) 719px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/vddDg7f9Gp93OgaqWwHu.png?auto=format&amp;w=1438 1438w&quot; style=&quot;max-width: 35vw;&quot; width=&quot;719&quot; /&gt;
  &lt;figcaption&gt;
    If the incoming request uses a &quot;safe&quot; method then the cookies will be sent.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This pattern is used for sites that may redirect the user out to a remote
service to perform some operation before returning, for example redirecting to a
third-party identity provider. Before the user leaves the site, a cookie is set
containing a single use token with the expectation that this token can be
checked on the returning request to mitigate
&lt;a href=&quot;https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html&quot; rel=&quot;noopener&quot;&gt;Cross Site Request Forgery (CSRF)&lt;/a&gt;
attacks. If that returning request comes via POST then it will be necessary to
mark the cookies as &lt;code&gt;SameSite=None; Secure&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;remote-resources&quot;&gt;Remote resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#remote-resources&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Any remote resource on a page may be relying on cookies to be sent with a
request, from &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags, &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags, and so on. Common use cases include
tracking pixels and personalizing content.&lt;/p&gt;
&lt;p&gt;This also applies to requests initiated from your JavaScript by &lt;code&gt;fetch&lt;/code&gt; or
&lt;code&gt;XMLHttpRequest&lt;/code&gt;. If &lt;code&gt;fetch()&lt;/code&gt; is called with the
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Fetch_API/Using_Fetch#Sending_a_request_with_credentials_included&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;credentials: &#39;include&#39;&lt;/code&gt; option&lt;/a&gt;
this is a good indication that cookies may well be expected on those requests.
For &lt;code&gt;XMLHttpRequest&lt;/code&gt; you should look for instances of the
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/withCredentials&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;withCredentials&lt;/code&gt; property&lt;/a&gt;
being set to &lt;code&gt;true&lt;/code&gt;. This is a good indication that cookies may well be expected
on those requests. Those cookies will need to be appropriately marked to be
included in cross-site requests.&lt;/p&gt;
&lt;h3 id=&quot;content-within-a-webview&quot;&gt;Content within a WebView &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#content-within-a-webview&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A WebView in a platform-specific app is powered by a browser and you will need to test if
the same restrictions or issues apply. In Android, if the WebView is powered by
Chrome the new defaults &lt;strong&gt;will not&lt;/strong&gt; immediately be applied with Chrome 84.
However the intent is to apply them in the future, so you should still test and
prepare for this. Additionally, Android allows its platform-specific apps to set cookies
directly via the
&lt;a href=&quot;https://developer.android.com/reference/android/webkit/CookieManager&quot; rel=&quot;noopener&quot;&gt;CookieManager API&lt;/a&gt;.
As with cookies set via headers or JavaScript, consider including
&lt;code&gt;SameSite=None; Secure&lt;/code&gt; if they are intended for cross-site use.&lt;/p&gt;
&lt;h2 id=&quot;how-to-implement-samesite-today&quot;&gt;How to implement &lt;code&gt;SameSite&lt;/code&gt; today &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#how-to-implement-samesite-today&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For cookies where they are only needed in a first-party context you should
ideally mark them as &lt;code&gt;SameSite=Lax&lt;/code&gt; or &lt;code&gt;SameSite=Strict&lt;/code&gt; depending on your
needs. You can also choose to do nothing and just allow the browser to enforce
its default, but this comes with the risk of inconsistent behavior across
browsers and potential console warnings for each cookie.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Cookie: first_party_var=value; SameSite=Lax&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;For cookies needed in a third-party context, you will need to ensure they are
marked as &lt;code&gt;SameSite=None; Secure&lt;/code&gt;. Note that you need both attributes together.
If you just specify &lt;code&gt;None&lt;/code&gt; without &lt;code&gt;Secure&lt;/code&gt; the cookie will be rejected. There
are some mutually incompatible differences in browser implementations though, so
you may need to use some of the mitigating strategies described in
&lt;a href=&quot;https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients&quot;&gt;Handling incompatible clients&lt;/a&gt; below.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Cookie: third_party_var=value; SameSite=None; Secure&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;handling-incompatible-clients&quot;&gt;Handling incompatible clients &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As these changes to include &lt;code&gt;None&lt;/code&gt; and update default behavior are still
relatively new, there are inconsistencies amongst browsers as to how these
changes are handled. You can refer to the
&lt;a href=&quot;https://www.chromium.org/updates/same-site/incompatible-clients&quot; rel=&quot;noopener&quot;&gt;updates page on chromium.org&lt;/a&gt;
for the issues currently known, however it&#39;s not possible to say if this is
exhaustive. While this is not ideal, there are workarounds you can employ during
this transitionary phase. The general rule though is to treat incompatible
clients as the special case. Do not create an exception for browsers
implementing the newer rules.&lt;/p&gt;
&lt;p&gt;The first option is to set both the new and old style cookies:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-cookie: 3pcookie=value; SameSite=None; Secure&lt;br /&gt;Set-cookie: 3pcookie-legacy=value; Secure&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Browsers implementing the newer behavior will set the cookie with the &lt;code&gt;SameSite&lt;/code&gt;
value, while other browsers may ignore or incorrectly set it. However, those
same browsers will set the &lt;code&gt;3pcookie-legacy&lt;/code&gt; cookie. When processing included
cookies, the site should first check for the presence of the new style cookie
and if it&#39;s not found, then fallback to the legacy cookie.&lt;/p&gt;
&lt;p&gt;The example below shows how to do this in Node.js, making use of the
&lt;a href=&quot;https://expressjs.com/&quot; rel=&quot;noopener&quot;&gt;Express framework&lt;/a&gt; and its
&lt;a href=&quot;https://www.npmjs.com/package/cookie-parser&quot; rel=&quot;noopener&quot;&gt;cookie-parser&lt;/a&gt; middleware.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;cookie-parser&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/set&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Set the new style cookie&lt;/span&gt;&lt;br /&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;3pcookie&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;value&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;sameSite&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;none&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;secure&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// And set the same value in the legacy cookie&lt;/span&gt;&lt;br /&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;3pcookie-legacy&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;value&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;secure&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; cookieVal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cookies&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;3pcookie&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// check the new style cookie first&lt;/span&gt;&lt;br /&gt;    cookieVal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cookies&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;3pcookie&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cookies&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;3pcookie-legacy&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// otherwise fall back to the legacy cookie&lt;/span&gt;&lt;br /&gt;    cookieVal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cookies&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;3pcookie-legacy&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The downside is that this involves setting redundant cookies to cover all
browsers and requires making changes both at the point of setting and reading
the cookie. However, this approach should cover all browsers regardless of their
behavior and ensure third-party cookies continue to function as before.&lt;/p&gt;
&lt;p&gt;Alternatively at the point of sending the &lt;code&gt;Set-Cookie&lt;/code&gt; header, you can choose to
detect the client via the user agent string. Refer to the
&lt;a href=&quot;https://www.chromium.org/updates/same-site/incompatible-clients&quot; rel=&quot;noopener&quot;&gt;list of incompatible clients&lt;/a&gt;
and then make use of an appropriate library for your platform, for example
&lt;a href=&quot;https://www.npmjs.com/package/ua-parser-js&quot; rel=&quot;noopener&quot;&gt;ua-parser-js&lt;/a&gt; library on Node.js.
It&#39;s advisable to find a library to handle user agent detection as you most
probably don&#39;t want to write those regular expressions yourself.&lt;/p&gt;
&lt;p&gt;The benefit of this approach is that it only requires making one change at the
point of setting the cookie. However, the necessary warning here is that user
agent sniffing is inherently fragile and may not catch all of the affected
users.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  Regardless of what option you choose, it&#39;s advisable to ensure you have a way of logging the levels of traffic that are going through the legacy route. Make sure you have a reminder or alert to remove this workaround once those levels drop below an acceptable threshold for your site.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;support-for-samesite=none-in-languages,-libraries,-and-frameworks&quot;&gt;Support for &lt;code&gt;SameSite=None&lt;/code&gt; in languages, libraries, and frameworks &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#support-for-samesite=none-in-languages,-libraries,-and-frameworks&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The majority of languages and libraries support the &lt;code&gt;SameSite&lt;/code&gt; attribute for
cookies, however the addition of &lt;code&gt;SameSite=None&lt;/code&gt; is still relatively new which
means that you may need to work around some of the standard behavior for now.
These are documented in the
&lt;a href=&quot;https://github.com/GoogleChromeLabs/samesite-examples&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;SameSite&lt;/code&gt; examples repo on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;getting-help&quot;&gt;Getting help &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookie-recipes/#getting-help&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cookies are all over the place and it&#39;s rare for any site to have completely
audited where they&#39;re set and used, especially once you throw cross-site use
cases in the mix. When you encounter an issue, it may well be the first time
anyone has encountered it - so don&#39;t hesitate to reach out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Raise an issue on the
&lt;a href=&quot;https://github.com/GoogleChromeLabs/samesite-examples&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;SameSite&lt;/code&gt; examples repo on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;blog a question on the
&lt;a href=&quot;https://stackoverflow.com/questions/tagged/samesite&quot; rel=&quot;noopener&quot;&gt;&amp;quot;samesite&amp;quot; tag on StackOverflow&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For issues with Chromium&#39;s behavior, raise a bug via the
&lt;a href=&quot;https://bit.ly/2lJMd5c&quot; rel=&quot;noopener&quot;&gt;[SameSite cookies] issue template&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Follow Chrome&#39;s progress on the
&lt;a href=&quot;https://www.chromium.org/updates/same-site&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;SameSite&lt;/code&gt; updates page&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Rowan Merewood</name>
    </author>
  </entry>
  
  <entry>
    <title>SameSite cookies explained</title>
    <link href="https://web.dev/samesite-cookies-explained/"/>
    <updated>2019-05-07T00:00:00Z</updated>
    <id>https://web.dev/samesite-cookies-explained/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This article is part of a series on the &lt;code&gt;SameSite&lt;/code&gt; cookie attribute changes that includes:  &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/understanding-cookies/&quot;&gt;Understanding cookies&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/samesite-cookie-recipes/&quot;&gt;SameSite cookies recipes&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://web.dev/schemeful-samesite/&quot;&gt;Schemeful Same-Site&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Each cookie contains a key-value pair along with a number of attributes that control when and where that cookie is used.&lt;/p&gt;
&lt;p&gt;The introduction of the &lt;code&gt;SameSite&lt;/code&gt; attribute (defined in
&lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00&quot; rel=&quot;noopener&quot;&gt;RFC6265bis&lt;/a&gt;)
allows you to declare if your cookie should be restricted to a first-party or
same-site context. It&#39;s helpful to understand exactly what &#39;site&#39; means here.
The site is the combination of the domain suffix and the part of the domain just
before it. For example, the &lt;code&gt;www.web.dev&lt;/code&gt; domain is part of the &lt;code&gt;web.dev&lt;/code&gt; site.&lt;/p&gt;
&lt;aside class=&quot;aside flow color-secondary-box-text bg-secondary-box-bg&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Highlighter pen&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M10.22 9.49l-5.91 6c-.77.8-.7 2.05.08 2.85L.77 22h5.68l.74-.75c.78.81 1.95.86 2.73.05l5.96-6.05-5.66-5.76zm12.46-4l-2.82-2.87c-.78-.8-2.07-.84-2.84-.04l-5.75 5.85 5.66 5.75 5.69-5.78c.77-.81.83-2.11.06-2.91z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Key Term&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  If the user is on &lt;code&gt;www.web.dev&lt;/code&gt; and requests an image from &lt;code&gt;static.web.dev&lt;/code&gt; then that is a &lt;strong&gt;same-site&lt;/strong&gt; request.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The &lt;a href=&quot;https://publicsuffix.org/&quot; rel=&quot;noopener&quot;&gt;public suffix list&lt;/a&gt; defines this, so it&#39;s not
just top-level domains like &lt;code&gt;.com&lt;/code&gt; but also includes services like &lt;code&gt;github.io&lt;/code&gt;.
That enables &lt;code&gt;your-project.github.io&lt;/code&gt; and &lt;code&gt;my-project.github.io&lt;/code&gt; to count as
separate sites.&lt;/p&gt;
&lt;aside class=&quot;aside flow color-secondary-box-text bg-secondary-box-bg&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Highlighter pen&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M10.22 9.49l-5.91 6c-.77.8-.7 2.05.08 2.85L.77 22h5.68l.74-.75c.78.81 1.95.86 2.73.05l5.96-6.05-5.66-5.76zm12.46-4l-2.82-2.87c-.78-.8-2.07-.84-2.84-.04l-5.75 5.85 5.66 5.75 5.69-5.78c.77-.81.83-2.11.06-2.91z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Key Term&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  If the user is on &lt;code&gt;your-project.github.io&lt;/code&gt; and requests an image from &lt;code&gt;my-project.github.io&lt;/code&gt; that&#39;s a &lt;strong&gt;cross-site&lt;/strong&gt; request.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;explicitly-state-cookie-usage-with-the-samesite-attribute&quot;&gt;Explicitly state cookie usage with the &lt;code&gt;SameSite&lt;/code&gt; attribute &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookies-explained/#explicitly-state-cookie-usage-with-the-samesite-attribute&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Introducing the &lt;code&gt;SameSite&lt;/code&gt; attribute on a cookie provides three different ways
to control this behaviour. You can choose to not specify the attribute, or you
can use &lt;code&gt;Strict&lt;/code&gt; or &lt;code&gt;Lax&lt;/code&gt; to limit the cookie to same-site requests.&lt;/p&gt;
&lt;p&gt;If you set &lt;code&gt;SameSite&lt;/code&gt; to &lt;code&gt;Strict&lt;/code&gt;, your cookie will only be sent in a
first-party context. In user terms, the cookie will only be sent if the site for
the cookie matches the site currently shown in the browser&#39;s URL bar. So, if the
&lt;code&gt;promo_shown&lt;/code&gt; cookie is set as follows:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Cookie: promo_shown=1; SameSite=Strict&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When the user is on your site, then the cookie will be sent with the request as
expected. However when following a link into your site, say from another site or
via an email from a friend, on that initial request the cookie will not be sent.
This is good when you have cookies relating to functionality that will always
be behind an initial navigation, such as changing a password or making a
purchase, but is too restrictive for &lt;code&gt;promo_shown&lt;/code&gt;. If your reader follows the
link into the site, they want the cookie sent so their preference can be
applied.&lt;/p&gt;
&lt;p&gt;That&#39;s where &lt;code&gt;SameSite=Lax&lt;/code&gt; comes in by allowing the cookie to be sent with
these top-level navigations. Let&#39;s revisit the cat article example from above
where another site is referencing your content. They make use of your photo of
the cat directly and provide a link through to your original article.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Look at this amazing cat!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://blog.example/blog/img/amazing-cat.png&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Read the &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://blog.example/blog/cat.html&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;article&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;And the cookie has been set as so:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Cookie: promo_shown=1; SameSite=Lax&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When the reader is on the other person&#39;s blog the cookie &lt;strong&gt;will not be sent&lt;/strong&gt;
when the browser requests &lt;code&gt;amazing-cat.png&lt;/code&gt;. However when the reader follows the
link through to &lt;code&gt;cat.html&lt;/code&gt; on your blog, that request &lt;strong&gt;will include&lt;/strong&gt; the
cookie. This makes &lt;code&gt;Lax&lt;/code&gt; a good choice for cookies affecting the display of the
site with &lt;code&gt;Strict&lt;/code&gt; being useful for cookies related to actions your user is
taking.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  Neither &lt;code&gt;Strict&lt;/code&gt; nor &lt;code&gt;Lax&lt;/code&gt; are a complete solution for your site&#39;s security. Cookies are sent as part of the user&#39;s request and you should treat them the same as any other user input. That means sanitizing and validating the input. Never use a cookie to store data you consider a server-side secret.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Finally there is the option of not specifying the value which has previously
been the way of implicitly stating that you want the cookie to be sent in all
contexts. In the latest draft of
&lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03&quot; rel=&quot;noopener&quot;&gt;RFC6265bis&lt;/a&gt; this
is being made explicit by introducing a new value of &lt;code&gt;SameSite=None&lt;/code&gt;. This means
you can use &lt;code&gt;None&lt;/code&gt; to clearly communicate that you intentionally want the cookie
sent in a third-party context.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Three cookies labelled None, Lax, or Strict depending on their context&quot; decoding=&quot;async&quot; height=&quot;456&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/1MhNdg9exp0rKnHpwCWT.png?auto=format&amp;w=1600 1600w&quot; style=&quot;max-width: 35vw&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Explicitly mark the context of a cookie as &lt;code&gt;None&lt;/code&gt;, &lt;code&gt;Lax&lt;/code&gt;, or &lt;code&gt;Strict&lt;/code&gt;.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  If you provide a service that other sites consume such as widgets, embedded content, affiliate programs, advertising, or sign-in across multiple sites then you should use &lt;code&gt;None&lt;/code&gt; to ensure your intent is clear.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;changes-to-the-default-behavior-without-samesite&quot;&gt;Changes to the default behavior without SameSite &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookies-explained/#changes-to-the-default-behavior-without-samesite&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While the &lt;code&gt;SameSite&lt;/code&gt; attribute is widely supported, it has unfortunately not
been widely adopted by developers. The open default of sending cookies
everywhere means all use cases work but leaves the user vulnerable to CSRF and
unintentional information leakage. To encourage developers to state their intent
and provide users with a safer experience, the IETF proposal,
&lt;a href=&quot;https://tools.ietf.org/html/draft-west-cookie-incrementalism-00&quot; rel=&quot;noopener&quot;&gt;Incrementally Better Cookies&lt;/a&gt;
lays out two key changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cookies without a &lt;code&gt;SameSite&lt;/code&gt; attribute will be treated as &lt;code&gt;SameSite=Lax&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cookies with &lt;code&gt;SameSite=None&lt;/code&gt; must also specify &lt;code&gt;Secure&lt;/code&gt;, meaning they require
a secure context.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Chrome implements this default behavior as of version 84.
&lt;a href=&quot;https://groups.google.com/d/msg/mozilla.dev.platform/nx2uP0CzA9k/BNVPWDHsAQAJ&quot; rel=&quot;noopener&quot;&gt;Firefox&lt;/a&gt;
has them available to test as of Firefox 69 and will make them default behaviors
in the future. To test these behaviors in Firefox, open
&lt;a href=&quot;http://kb.mozillazine.org/About:config&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;about:config&lt;/code&gt;&lt;/a&gt; and set
&lt;code&gt;network.cookie.sameSite.laxByDefault&lt;/code&gt;.
&lt;a href=&quot;https://groups.google.com/a/chromium.org/d/msg/blink-dev/AknSSyQTGYs/8lMmI5DwEAAJ&quot; rel=&quot;noopener&quot;&gt;Edge&lt;/a&gt;
also plans to change its default behaviors.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  This article will be updated as additional browsers announce support.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;samesite=lax-by-default&quot;&gt;&lt;code&gt;SameSite=Lax&lt;/code&gt; by default &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookies-explained/#samesite=lax-by-default&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure class=&quot;compare flow&quot; data-type=&quot;worse&quot; data-size=&quot;full&quot;&gt;&lt;p class=&quot;compare__label&quot;&gt;No attribute set&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Cookie: promo_shown=1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figcaption class=&quot;compare__caption&quot;&gt;
&lt;p&gt;If you send a cookie without any &lt;code&gt;SameSite&lt;/code&gt; attribute specified…&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;compare flow&quot; data-type=&quot;better&quot; data-size=&quot;full&quot;&gt;&lt;p class=&quot;compare__label&quot;&gt;Default behavior applied&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Cookie: promo_shown=1; SameSite=Lax&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figcaption class=&quot;compare__caption&quot;&gt;
&lt;p&gt;The browser will treat that cookie as if &lt;code&gt;SameSite=Lax&lt;/code&gt; was specified.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;While this is intended to apply a more secure default, you should ideally set an
explicit &lt;code&gt;SameSite&lt;/code&gt; attribute rather than relying on the browser to apply that
for you. This makes your intent for the cookie explicit and improves the chances
of a consistent experience across browsers.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  The default behaviour applied by Chrome is slightly more permissive than an explicit &lt;code&gt;SameSite=Lax&lt;/code&gt; as it will allow certain cookies to be sent on top-level POST requests. You can see the exact details on &lt;a href=&quot;https://groups.google.com/a/chromium.org/d/msg/blink-dev/AknSSyQTGYs/YKBxPCScCwAJ&quot;&gt;the blink-dev announcement&lt;/a&gt;. This is intended as a temporary mitigation, you should still be fixing your cross-site cookies to use &lt;code&gt;SameSite=None; Secure&lt;/code&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;samesite=none-must-be-secure&quot;&gt;&lt;code&gt;SameSite=None&lt;/code&gt; must be secure &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookies-explained/#samesite=none-must-be-secure&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure class=&quot;compare flow&quot; data-type=&quot;worse&quot; data-size=&quot;full&quot;&gt;&lt;p class=&quot;compare__label&quot;&gt;Rejected&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Cookie: widget_session=abc123; SameSite=None&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figcaption class=&quot;compare__caption&quot;&gt;
&lt;p&gt;Setting a cookie without &lt;code&gt;Secure&lt;/code&gt; &lt;strong&gt;will be rejected&lt;/strong&gt;.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;compare flow&quot; data-type=&quot;better&quot; data-size=&quot;full&quot;&gt;&lt;p class=&quot;compare__label&quot;&gt;Accepted&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Cookie: widget_session=abc123; SameSite=None; Secure&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figcaption class=&quot;compare__caption&quot;&gt;
&lt;p&gt;You must ensure that you pair &lt;code&gt;SameSite=None&lt;/code&gt; with the &lt;code&gt;Secure&lt;/code&gt; attribute.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You can test this behavior as of Chrome 76 by enabling
&lt;code&gt;about://flags/#cookies-without-same-site-must-be-secure&lt;/code&gt; and from Firefox 69
in &lt;a href=&quot;http://kb.mozillazine.org/About:config&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;about:config&lt;/code&gt;&lt;/a&gt; by setting
&lt;code&gt;network.cookie.sameSite.noneRequiresSecure&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You will want to apply this when setting new cookies and actively refresh
existing cookies even if they are not approaching their expiry date.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  If you rely on any services that provide third-party content on your site, you should also check with the provider that they are updating their services. You may need to update your dependencies or snippets to ensure that your site picks up the new behavior.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Both of these changes are backwards-compatible with browsers that have correctly
implemented the previous version of the &lt;code&gt;SameSite&lt;/code&gt; attribute, or just do not
support it at all. By applying these changes to your cookies, you are making
their intended use explicit rather than relying on the default behavior of the
browser. Likewise, any clients that do not recognize &lt;code&gt;SameSite=None&lt;/code&gt; as of yet
should ignore it and carry on as if the attribute was not set.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  A number of older versions of browsers including Chrome, Safari, and UC browser are incompatible with the new &lt;code&gt;None&lt;/code&gt; attribute and may ignore or restrict the cookie. This behavior is fixed in current versions, but you should check your traffic to determine what proportion of your users are affected. You can see the &lt;a href=&quot;https://www.chromium.org/updates/same-site/incompatible-clients&quot;&gt;list of known incompatible clients on the Chromium site&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;samesite-cookie-recipes&quot;&gt;&lt;code&gt;SameSite&lt;/code&gt; cookie recipes &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/samesite-cookies-explained/#samesite-cookie-recipes&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For further detail on exactly how to update your cookies to successfully handle
these changes to &lt;code&gt;SameSite=None&lt;/code&gt; and the difference in browser behavior, head to
the follow up article, &lt;a href=&quot;https://web.dev/samesite-cookie-recipes&quot;&gt;SameSite cookie recipes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Kind thanks for contributions and feedback from Lily Chen, Malte Ubl, Mike
West, Rob Dodson, Tom Steiner, and Vivek Sekhar&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cookie hero image by
&lt;a href=&quot;https://unsplash.com/photos/UiP3uF5JRWM?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Pille-Riin Priske&lt;/a&gt;
on
&lt;a href=&quot;https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content>
    <author>
      <name>Rowan Merewood</name>
    </author>
  </entry>
</feed>
