SameSite Cookies
The SameSite cookie attribute was first drafted in 2016. Targeting cross-origin requests, it defines under which circumstances a cookie should be sent to the server, putting cookies into three different classes:
SameSite=None
Send the cookie whenever a request is made to the cookie domain, be it cross-origin or on the same site. This is how cookies have behaved the last decades.
SameSite=Lax
Like None
, but only send the cookie in a first-party context (meaning the URL in the address bar matches the cookie domain). Do not send it with the following cross-origin requests: non-GET, AJAX, iframe, image requests etc. It saves the user from cross-site request forgery.
SameSite=Strict
Like Lax
, but only send the cookie if the request was initiated from the cookie domain. The cookie will not be sent if the user e.g. opens a link from an email. It will only be sent with same-origin requests that are triggered from the cookie domain.
A cookie without the SameSite
attribute will currently be handled as if it was sent with SameSite=None
. However, Google announced to start enforcing usage of the SameSite
attribute in Chrome in February 2020, meaning it will handle cookies without the SameSite
attribute as if they were sent with SameSite=Lax
. Strict
is a good idea e.g. for an CSRF cookie.
What this means for web development
Chrome moving to SameSite=Lax
as default forces web developers to handle this change. Considering its market share, other browser vendors will move along.
If your application is running on a single domain without any cross-origin communication, you're fine: nothing to do.
A good default is SameSite=Lax
. In fact, you can add SameSite=Lax
to all cookies you are setting (e.g. with a Rails middleware) and it will run just fine in the most cases. Some breaking use cases to watch out for:
- Rendering in an iframe
- When your application (or parts of it) are rendered inside an iframe,
SameSite=Lax
will prevent your cookies to be sent along (unless the iframe is embedded on its own domain). If you need tracking or authentication cookies in an iframe context, setSameSite=None
on these cookies. - Cross-domain API
- When you're offering an API that is queried from browsers on various domains,
SameSite=Lax
will prevent your cookies to be sent along. SetSameSite=None
on cookies you need to receive on the API. - Cross-domain non-GET requests
- A
Lax
cookie will not be sent withPOST
,DELETE
,OPTIONS
or any other request. If you need an authentication cookie on these, you must either make the cookieSameSite=None
orSameSite=Strict
. - Handling incompatible clients
- A few web browsers will reject cookies with
SameSite=None
:- Chrome 51-66
- UC browser < 12.13.2 on Android
- All browsers on iOS 12
- Safari on Mac OS 10.14 Mojave
Testing in advance
To test the effect of the new Chrome behavior on your site or cookies you manage, you can go to chrome://flags in Chrome 76+ and enable the “SameSite by default cookies” and “Cookies without SameSite must be secure” experiments.
Resources
- A good overview in German
- Prose spec of the SameSite attribute, illustrated
- A sceptical view on the topic
- RFC
By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.