My first encounter with SameSite attribute in cookies

My first encounter with SameSite attribute in cookies


I have been working on enhancing a legacy project which was based on monolith architecture (, let’s call that project ABC hosted at for convenience.

This is how the legacy system worked:

  • whenever a request is made to the system( and it doesn’t match the defined api routes(/api), it responds to that request with HTML (client/frontend files).

  • When the user signs in, the backend responds with Set-Cookie which contains a JWT and that cookie was being sent on all the further calls to establish authentication. This was working fine as all the calls were being made from itself and the required JWT containing cookie was automatically being sent to the backend.

As a part of an enhancement to the architecture of this project, the frontend and backend were separated and now the backend was hosted at and the frontend was hosted at and this started breaking the login system.
After some debugging, I realized that this is breaking due to the cookie being set on another domain and the SameSite attribute-related changes that have happened across browsers.

Understanding the ‘SameSite’ Attribute in cookies

The SameSite attribute of the Set-Cookie HTTP response header allows you to declare if your cookie should be restricted to a first-party or same-site context.
- MDN Web Docs

When the cookie is considered as first-party (or same-site context)?
A cookie is associated with a particular domain and scheme (such as http or https), and may also be associated with subdomains if the Set-Cookie Domain attribute is set. If the cookie domain and scheme match the current page, the cookie is considered to be from the same site as the page and is referred to as a first-party cookie.

Recently there have been changes regarding the SameSite attribute standards, Which are :

  1. Earlier if no SameSite attribute were specified, the cookies were being sent for all requests, and now if the SameSite attribute is not specified, it would have defaulted to Lax.
    Lax — Cookies are not sent on normal cross-site subrequests (for example to load images or frames into a third party site), but are sent when a user is navigating to the origin site (i.e., when following a link)

  2. Developers must use a new cookie setting, SameSite=None, to designate cookies for cross-site access. Cookies with SameSite=None must now also specify the ‘secure’ attribute so cross-site cookies can only be accessed over HTTPS connections.

  3. Cookies from the same domain are no longer considered to be from the same site if sent using a different scheme i.e, http: / https:/

Getting back to the issue

So, as mentioned above, after the frontend and backend were separated, frontend being at and backend being at, when the user was logging in, was responding cookie containing JWT but any further communication was failing because all the further communication was being made from and those calls did not contain the cookies by default so authentication was failing.


An immediate solution to make sure that the login works similar to how it worked in the legacy monolith app, was to make sure that cookies can be sent from the browser to whenever the frontend at calls any APIs.

To enable this:

  • The cookie should have SameSite=None so that it can be sent by default in third party contexts (which was the default behavior before SameSite was introduced)

  • the cookie has to be set as secure, to comply with guidelines for SameSite=None

  • The frontend and backend both have to be on https, so that the secure cookie can be transmitted

This fixed the login issue, and the cookie behavior is now more or less similar to the earlier setup.


  • The current solution with SameSite=None gets us back to the original working implementation, which works fine, but still has all the drawbacks (csrf, privacy) which are supposed to be solved by the introduction of SameSite cookies.

  • We still need to have csrf protection enabled

  • We still need to set this cookie as httpOnly so that it can’t be leaked through Javascript