Cookies and Iframes
It’s been a while since the last time you had the pleasure of having your application consumed from an Iframe. But some legacy application “needs” to do exactly that. You test the “integration” and it doesn’t work. The cookies for the requests made by the Iframe don’t make its way to the server.
Sounds Familiar? It happened to me some time ago and it took some digging around to understand and diagnose the problem. This kind of scenario used to work without problems but now, with modern browsers, you need to do a couple of things to make your iframed stuff work properly.
Solution
When I bump into this kind of problem I usually appreciate finding a post that offers a solution as fast as possible so here it goes:
Set-Cookie: session=your_session; SameSite=None; Secure
You need to set your cookie with the attributeSameSite=None
and also including the attribute Secure
.
In Spring Boot
Understanding the problem
Now, with the problem already solved, we can use a couple of minutes to understand what we have just done.
First-party and Third-party cookies
Cookies that match the domain of the current site are referred to as first-party cookies. Cookies from domains other than the current site are referred to as third-party cookies.
For a long time, both kinds of cookies were treated equally: every time you request an URL all the cookies for that URL were sent with the request. There are a variety of problems associated with this behavior:
- Allows Cross-site request forgery (CSRF) attacks.
- Adds overhead to the request, sending potentially unneeded stuff.
- Can be used to track user activity across multiple sites.
State cookie usage with the SameSite
attribute
RFC6265bis defines a new attribute for cookies: SameSite
. This attribute allows you to declare if your cookie should be restricted to a first-party or same-site context. Possible values:
None
: cookies will be sent also in third-party contexts.Strict
: cookies will only be sent in a first-party context (when the domain in the browser’s URL bar matches your cookie domain).Lax
: cookies will be sent in a first-party context and also sent along with top-level navigations. With theStrict
policy, cookies are not sent when you navigate to top-level URLs. An example of the scenarios solved by theLax
value, extracted from RFC6265bis:
Consider the scenario in which a user reads their email at MegaCorp
Inc’s webmail provider “https://example.com/". They might expect
that clicking on an emailed link to “https://projects.com/secret/
project” would show them the secret project that they’re authorized
to see, but if “projects.com” has marked their session cookies as
“SameSite=Strict”, then this cross-site navigation won’t send them along
with the request. “projects.com” will render a 404 error to avoid
leaking secret information, and the user will be quite confused.
Defaults change
When your cookies don’t set SameSite
your browser has to guess your intentions. Browsers used to default to None
when the attribute wasn’t set but this behavior is changing.
The IETF proposal, Incrementally Better Cookies proposes two important changes:
- Cookies without a
SameSite
attribute will be treated asSameSite=Lax
. - Cookies with
SameSite=None
must also specifySecure
, meaning they require a secure context.
Chrome implements this default behavior as of version 84 and other browsers are following in the near future.
Secure cookies
We have just reached the second part of the solution: the Secure
attribute.
This attribute can be set by the application server when sending a new cookie to the user within an HTTP Response. The purpose of the secure flag is to prevent cookies from being observed by unauthorized parties due to the transmission of a cookie in clear text.
Browsers that support the secure flag will only send cookies with the secure flag when the request is going to an HTTPS page.
So, in addition to SameSite=None
and Secure
, the URLs used inside the Iframe must be secure URLs starting with https.
Wrapping up
In this story, we have followed a problem-solution angle but we can extract more general rules on when to use Strict
, Lax
or None
as values for SameSite
:
Lax
: the choice for cookies that are always needed in order to correctly display the site. As we saw earlier, you should use this value for any cookie needed when the user arrives at a top-level URL following a link from another site.Strict
: useful for cookies related do actions taken by the user and not affecting the display of the site.None
: the choice when we need cookies available to all our application’s URLs (top-level or not) in third-party contexts. Example: Youtube’s login cookies are set with this attribute in order to be sent whenever you see a video embedded in any website different than youtube itself.
In the case of the Secure
flag, it should be set for all your cookies. In 2020 you should be forcing https for all your clients so having all cookies as Secure
should not be a problem.