SameSite cookies explained

Browser Support

  • 51
  • 16
  • 60
  • 13

Source

Every cookie contains a key-value pair along with a number of attributes that control when and where that cookie is used.

The introduction of the SameSite attribute (defined in RFC6265bis) lets you declare whether your cookie is restricted to a first-party or same-site context. It's helpful to understand exactly what 'site' means here. The site is the combination of the domain suffix and the part of the domain just before it. For example, the www.web.dev domain is part of the web.dev site.

Key term: If the user is on www.web.dev and requests an image from static.web.dev, that's a same-site request.

The public suffix list defines what pages count as being on the same site. It doesn't just depend on top-level domains like .com, but can also include services like github.io. This enables your-project.github.io and my-project.github.io to count as separate sites.

Key term: If the user is on your-project.github.io and requests an image from my-project.github.io that's a cross-site request.

Use the SameSite attribute to declare cookie usage

The SameSite attribute on a cookie provides three different ways to control this behaviour. You can choose to not specify the attribute, or you can use Strict or Lax to limit the cookie to same-site requests.

If you set SameSite to Strict, your cookie can only be sent in a first-party context; that is, if the site for the cookie matches the site shown in the browser's address bar. So, if the promo_shown cookie is set as follows:

Set-Cookie: promo_shown=1; SameSite=Strict

When the user is on your site, the cookie is sent with the request as expected. However, if the user follows a link into your site from another one, the cookie isn't sent on that initial request. This is good for cookies relating to features that are always behind an initial navigation, such as changing a password or making a purchase, but it's too restrictive for a cookie like promo_shown. If your reader follows the link into the site, they want the cookie sent so their preference can be applied.

SameSite=Lax allows the browser to send the cookie with these top-level navigations. For example, if another site references your site's content, in this case by using your cat photo and providing a link to your article as follows:

<p>Look at this amazing cat!</p>
<img src="https://blog.example/blog/img/amazing-cat.png" />
<p>Read the <a href="https://blog.example/blog/cat.html">article</a>.</p>

With a cookie set to Lax as follows:

Set-Cookie: promo_shown=1; SameSite=Lax

When the browser requests amazing-cat.png for the other person's blog, your site doesn't send the cookie. However, when the reader follows the link to cat.html on your site, that request does include the cookie.

We recommend using SameSite in this way, setting cookies that affect website display to Lax, and cookies related to user actions to Strict.

You can also set SameSite to None to indicate that you want the cookie to be sent in all contexts. If you provide a service that other sites consume such as widgets, embedded content, affiliate programs, advertising, or sign-in across multiple sites, use None to ensure your intent is clear.

Three cookies labelled None, Lax, or Strict depending on their context
Explicitly mark the context of a cookie as None, Lax, or Strict.

Changes to the default behavior without SameSite

Browser Support

  • 80
  • 86
  • x

The SameSite attribute is widely supported, but it hasn't been widely adopted. In the past, setting cookies without SameSite defaulted to sending them in all contexts, which leaves users vulnerable to CSRF and unintentional information leakage. To encourage developers to state their intent and provide users with a safer experience, the IETF proposal, Incrementally Better Cookies lays out two key changes:

  • Cookies without a SameSite attribute are treated as SameSite=Lax.
  • Cookies with SameSite=None must also specify Secure, meaning they require a secure context.

Both of these changes are backwards-compatible with browsers that have correctly implemented the previous version of the SameSite attribute, as well as browsers that don't support earlier SameSite versions. They're intended to reduce developers' reliance on browsers' default behavior by making cookie behavior and intended use explicit. Any clients that don't recognize SameSite=None should ignore it.

SameSite=Lax by default

If you send a cookie without specifying its SameSite attribute, the browser treats that cookie as if it were set to SameSite=Lax. We still recommend explicitly setting SameSite=Lax to make your user experience more consistent across browsers.

SameSite=None must be secure

When you create cross-site cookies using SameSite=None, you must also set them to Secure for the browser to accept them:

Set-Cookie: widget_session=abc123; SameSite=None; Secure

You can test this behavior as of Chrome 76 by enabling about://flags/#cookies-without-same-site-must-be-secure, and from Firefox 69 by setting network.cookie.sameSite.noneRequiresSecure in about:config.

We also recommend updating existing cookies to Secure as soon as possible. If you rely on services that provide third-party content on your site, make sure your service provider updates their cookies, and update any snippets or dependencies on your site to make sure it uses the new behavior.

For further details on updating your cookies to successfully handle these changes to SameSite=None and the differences in browser behavior, see the follow up-article, SameSite cookie recipes.

Kind thanks for contributions and feedback from Lily Chen, Malte Ubl, Mike West, Rob Dodson, Tom Steiner, and Vivek Sekhar.

Cookie hero image by Pille-Riin Priske on Unsplash