Winter is coming… A cookie day for people and their agents – browsers, that may break your user experience or even affect your life… Will it be a global Armageddon of the Web, or just cause a local malfunction of some old-time sites? It’s time to figure it out.
First of all, please welcome to the world of HTTP cookies. Mozilla Developer Network gives the following definition of cookie:
An HTTP cookie (web cookie, browser cookie) is a small piece of data that a server sends to the user’s web browser. The browser may store it and send it back with the next request to the same server.
It was intended to introduce the state of a web session for the stateless HTTP protocol. Cookies are set by a server and then sent back by the agent with every request to the server. That, in turn, allows to manage the session, personalize user’s preferences, or track user behavior.
Be Aware! Confidential information must never be stored in cookies, as the entire mechanism is totally insecure. The cookie values are visible to the end-user and can be changed by him or a man-in-the-middle. Cookies are often used to identify a user and their authenticated session, so stealing a cookie can lead to hijacking the session as well. Common ways to do that include Social Engineering or exploiting cross-site scripting (XSS) vulnerability in the application. That is why the proper baking of the cookies is so important.
Besides a data payload, the cookie may also have additional settings, instructing the user’s browser how to handle it. For instance, the cookie could be a session one that is deleted when the agent shuts down, or a permanent one, expiring at a specific date (Expires) or after a specific length of time (Max-Age).
All these instructions along with a cookie itself are specified by the server in the dedicated Set-Cookie header.
Set-Cookie: <cookie-name>=<value>[; <directive>[; <directive2>…]]
All the directives could be split in two major parts.
Directive
Meaning
<none>
Expires
The maximum lifetime of the cookie in HTTP-date format.
Max-Age
Directive
Meaning
Domain
It defines the scope of the cookie: what hosts the cookies should be sent to.
If omitted, it defaults to the host of the current document URL, not including subdomains.
If a domain is specified, subdomains are always included.
Note: A cookie for a domain that does not include the server that set it should be rejected by the user agent.
Path
Secure
HttpOnly
SameSite
Strict
Lax
None
The browser will send cookies with both cross-site requests and same-site requests.
In general, a cookie must not be sent with cross-origin requests (where the site is defined by the registrable domain), providing some protection against cross-site request forgery attacks (CSRF).
Note: Browsers are migrating to have cookies default to SameSite=Lax. If a cookie is needed to be sent cross-origin, opt out of the SameSite restriction using the None directive. The None directive requires the Secure attribute.
<prefixes>
__Secure
Cookies with names starting with __Secure-must be set with Secure flag from a secure page (TLS aka HTTPS).
Now we are ready to dive into technical details about the upcoming changes in browser behavior. Google Chrome will be the first browser to roll out a change that might not be compatible with a web application. Here they are:
Since Chrome 80, cookies that do not specify a SameSite attribute will be treated as if they were SameSite=Lax with the additional behavior that they will still be included in POST requests to ease the transition for existing sites. Cookies that still need to be delivered in a cross-site context can explicitly request SameSite=None, and must also be marked Secure and delivered over HTTPS.
When a web application implements SSO, several redirects happen under the hood for the user authentication from the agent to idP and back with authentication confirmation. That confirmation is represented by a token sent back to the app. The app performs the token validation for which it needs information stored in the session. Without any updates, the cookie carrying the session or authentication request binding info would no longer be attached to the POST response, resulting in the failure of the response validation checks and the inability of the end-user to sign in to the app.
The short answer is: it brings more security. Previously, a vulnerability could cause an HTTP form to be submitted from the attacker’s context to the app that uses the attached POST request cookie to identify the end user’s session and execute a malicious action – for instance, a money transfer to the attacker. With the changes applied, the attack would not work because the POST is done from a different origin, the cookie will not be attached, and the action will fail. This change allows users to be protected by default but still allows applications to opt in for the less secure mode.
That’s it. Now you know what’s going on, so handle this smoothly.
Happy coding!