In this post, we will cover changes coming to Chrome (and other browsers) that affect how third-party cookies are handled—specifically SameSite
changes, how to test to see if your site is impacted and how to fix it.
What is SameSite
and why the big change?
Back in May 2019, Chrome announced its plan to develop a secure-by-default model for handling cookies. This initiative highlights Chrome’s promise of a more secure and faster browsing experience. Chrome's goal is to increase transparency, choice and control. Users should be aware of how they are tracked, who is tracking them, and ways to control the information shared. With the influx of privacy concerns and potential cross-site attacks, Chrome is taking action to protect its users. These changes will dramatically impact advertisers, publishers, or any company relying on cookies to target their audience. Be sure to prepare in advance so your users won't experience disruptions.
Now, the day is finally at hand. Starting February 4, 2020, Google Chrome will stop sending third-party cookies in cross-site requests unless the cookies are secured and flagged using an IETF standard called SameSite
.
What does this mean? What are third-party cookies? What are cross-site request?
When you visit a website, a browser cookie is generated and saved inside a folder in your web browser. This browser cookie is then used as a way to identify you and provide a personalized browsing experience.
There are two types of cookies — first-party and third-party. Both types can hold the same information; however, they are accessed and created differently.
As illustrated above, if you visit website a.com
and you attempt to access a service from the same domain name a.com
, cookies generated will be considered first-party cookies. Being that the cookies were created by the same site, you'll be able to enjoy same-site luxuries while visiting a.com
's web service. These luxuries include saved login information, shopping cart items, site preferences, etc.
Whereas, if you visit a website a.com
but that page includes content (image, iframe, etc.) from a different domain name b.com
, cookies set by b.com
will be considered third-party cookies because they come from a different name than in the URL bar: a.com
.
These cookies were created by a different site and b.com
accessing them from a.com
(or any other domain) would constitute a cross-site request. A page on a.com
making requests to b.com
(for images, iframes, etc.) is what allows services like Facebook, Google Analytics, Doubleclick, etc. to track users and provide online-advertisements. In that example, Facebook, Google, and Doubleclick are the b.com
. This allows, for example, Doubleclick to show targeted ads to you on multiple other sites you visit, like a news site, a hotel site, or a blog you read.
As previously stated, Google Chrome will stop sending third-party cookies in cross-site requests unless the cookies are secured and flagged using an IETF standard called SameSite
. In other words, the content from b.com
(images, iframe, etc.) on a.com
’s page will no longer be able to access b.com
's cookies unless those cookies are secured and flagged appropriately.
Why is Google making such a huge change?
Sharing cross-site cookies is not always an issue; however, it has the potential for abuse. Google Chrome's current behavior allows third-party websites to access all cookies by default. This creates the possibility of cross-site request forgery (CSRF) attacks, other security vulnerabilities and privacy leaks.
What’s cross-site request forgery (CSRF)?
Cross-site request forgery is a web security vulnerability that allows a hacker to exploit users through session surfing or one-click attacks. For example, hackers can trick an innocent user to click a believable link. If this user is already logged into a website the hacker wants to access, the hacker can surf on the already authenticated session and make request to a site the user didn't intend to make. Being that the user already authenticated, the site cannot distinguish between the forged or legitimate request.
There are a few ways to create these malicious commands: image tags, link tags, hidden forms, and JavaScript XMLHttpRequests. With Chrome's current default behavior, the requested cookie will be sent by default, and the hacker will have access to the user's session, which means they are effectively logged in as the user. To fight against this web vulnerability, web frameworks often require unique tokens/identifiers that are not accessible to attackers and would not be sent along (like cookies) with requests.
As an example, let’s assume you sign into your bank account.
www.bankpal.com
While browsing your transaction history, you get an email letting you know about a recent suspicious transaction. To investigate further, the email requires you to log into your bank account. It provides a convenient link for you as well.
💡Note: You are still logged in to BankPal in another tab.
The link’s HTML is as follows:
<a href="http://www.bank.com/transfer?acct=888888&amount=100000">Log In</a>
The hacker has already studied BankPal so they know how to mimic account transfers quite well. For example, here is how BankPal typically creates money transfers:
GET http://www.bankpal.com/transfer?acct=AccountId&amount=DollarAmount HTTP/1.1
This hacker has sent this email to a large number of bank customers and they know at least one person will click this believable link.
You are that one customer.
From a quick glance, this email looks legitimate. There is no way it could be suspicious and cause harm to a user's account. It even has the BankPal logo! With full trust, you click the link. Since you are already authenticated in the previous tab, clicking that link ends up creating an unauthorized transaction behind the scenes. This attacker has forged your identity, transferred $100,000 from your account, and has completely ruined your life (or at least your bank account) in seconds.
Let's say BankPal only allows a POST
request for money transfers. It would be impossible to create a malicious request using an <a href>
tag. This attacker could very well create a <form>
tag instead with automatic execution of the embedded JavaScript.
This form's HTML code could look like this:
<body onload="document.forms[0].submit()">
<form action="http://www.bankpal.com/transfer" method="POST">
<input type="hidden" name="acct" value="AttackerAccountId"/>
<input type="hidden" name="amount" value="100000"/>
<input type="submit" value="Log In"/>
</form>
</body>
In a real-life scenario, the example above would not happen. Banks prevent CSRF attacks using dynamically generated session tokens, session timeouts and other preventive methods. And now, with the SameSite
attribute Strict
(read more below), banks have yet another preventive measure. Large companies have found methods of protection; however, there are lots of smaller websites without protection. If an attacker can forge a transaction, they can also forge a password reset request, an email change request, and then gain full control of an account or web application.
How is Chrome protecting users against CSRF attacks?
To alleviate this issue, Chrome version 51 (2016-05-25) introduced the concept of the SameSite attribute. With the SameSite attribute, website developers have the power to set rules around how cookies are shared and accessed.
The SameSite
attribute can be set with the following values: Strict
, Lax
, or None
.
Strict: Restricts cross-site sharing altogether.
Cookies with this setting can be accessed only when visiting the domain from which it was initially set. In other words, Strict
completely blocks a cookie being sent to a.com
when a page from b.com
makes the request. Even when clicking a top-level link on a third-party domain to your site, the browser will refuse to send the cookie. This option would be best for applications that require high security, such as banks.
Lax: All the sites belonging to the same domain can set and access cookies.
Unlike None
where cookies are always sent, Lax
cookies are only sent on same-site request like Strict
. However, Lax
allows top-level (sometimes called public suffix) navigation access with a safe HTTP method, like HTTP GET
. The cookie will not be sent with cross-domain POST
requests or when loading the site in a cross-origin frame, but it will be sent when you navigate to the site via a standard top-level <a href=...>
link.
None: Allows third-party cookies to track users across sites.
Cookies with this setting will work the same way as cookies work today. Cookies will be able to be used across sites.
💡Note that you need both the None
and Secure
attributes together. If you just specify None
without Secure
the cookie will be rejected. Secure
ensures that the browser request is sent by a secure (HTTPS) connection.
Real-world example of the difference between Strict
and Lax
The None
attribute is pretty understandable; however, there seems to be confusion around Strict
and Lax
. Let's dive into a real-world example.
Let's say you are the CEO of TalkToMe, Inc., a feature rich commenting system. You allow your users to embed TalkToMe on their websites and they gain social network integration, advanced moderation options and other extensive community functions. If TalkToMe, Inc.'s first-party cookies are set to Lax
, your customers are still able to access their embedded comments. If TalkToMe, Inc.'s first-party cookies are set to Strict
, your customers will not be able to access data from an external site.
Chrome 80 SameSite
update
With the Chrome 51 update, Google gave website developers power to set rules around how cookies are shared; however, many developers don't follow the recommended practice. Instead of leaving the user's cookies exposed to potential security vulnerabilities (allowing third-party requests by default), the Chrome 80 update takes the power back and sets all cookies to SameSite=Lax
by default. In other words, Chrome has decided to make all cookies limited to first-party context by default, and will require developers to mark a cookie as needing third-party visibility using SameSite=None
explicitly.
“We’ve been focused on giving users transparency and choice over how they are tracked on the web through easy to use controls.”
- Ben Galbraith, Director, Chrome Product Management
Will this change break anything?
This SameSite
update requires explicit labeling for third-party cookies. Cookies that aren’t labeled appropriately may cease to function in Chrome. Even more than that: all cookies previously set may no longer be accessible.
How many users will this change affect?
According to the online traffic monitor StatCounter, Chrome is the most popular web browser, and this change will affect 64% of the world’s internet users in 2020. Keep reading to find out how you can keep this change from affecting your users!
Will my website be affected?
If either of the following is true, you will be affected and you must update your cookies:
- If your website integrates with external services for advertising, content recommendations, third-party widgets, social media embeds, or any custom integration that relies on cookies
- If your website uses non-secure (HTTP rather than HTTPS) browser access
Prepare for Chrome 80 updates
Step 1: Enabling SameSite
Chrome flags and test to see if your site faces potential SameSite
errors
As of Chrome 76, you can enable the new #same-site-by-default-cookies
flag and test your site before the February 4, 2020 deadline.
Let's enable the flag:
- Go to chrome://flags/
- Enable #same-site-by-default-cookies and #cookies-without-same-site-must-be-secure
- Restart the browser for the changes to take effect.
- Visit your website and see if you can spot error messages in the console of your browser's dev tools.
If you see error messages like the one above, this means your site is not ready for the 2020 Chrome 80 release. You should continue reading to learn how to set your cookies.
Step 2: Fixing cookie errors using appropriate attributes
Common use cases: Auditing your cookie usage
Chrome, Firefox, Edge, and other browsers will also change their default cookie behavior to the following:
- Cookies without a
SameSite
attribute will be treated asSameSite=Lax
(See variants below), meaning all cookies will be restricted to first-party context only. If you need third-party access, you will need to update your cookies. - Cookies needing third-party access must specify
SameSite=None; Secure
to enable access.
If you don't know whether you provide cookies that are intended for cross-site usage, some common use-cases are
- You present ads on your website.
- You present content in an
<iframe>
. - You present content within a WebView.
- You present images from another site on your website.
- You embed content shared from other sites, such as videos, maps, code samples, chat widgets and social post.
- You use third-party services on your website like Facebook, Twitter, Instagram, LinkedIn, Gravatar, Google Calendar, User Tracking (CrazyEgg, Google Analytics, etc.), CRM and/or reservations, booking, anti-fraud and payments services.
💡 NOTE: Cookie warnings triggered from domains you don't control will need to be set appropriately by the domain owner. If you are getting a warning like this from Google, Google will have to set this cookie appropriately. If the warning messages list a domain you control, you will need to add the correct attributes.
(index):1 A cookie associated with a resource at http://google.com/ was set with
SameSite=None but without Secure. A future release of Chrome will only deliver
cookies marked SameSite=None if they are also marked Secure. You can review cookies
in developer tools under Application>Storage>Cookies and see more details at
https://www.chromestatus.com/feature/5633521622188032.
Knowing which attribute to use
First, a quick recap of SameSite
attributes:
Value | Description |
---|---|
Strict | Cookies with this setting can be accessed only when visiting the domain from which it was initially set. In other words, Strict completely blocks a cookie being sent to a.com when it is being sent from a page on b.com (i.e. b.com is in the URL bar). Even when clicking a top-level link on a third-party domain to your site, the browser will refuse to send the cookie. This option would be best for applications that require high security, such as banks. |
Lax | Unlike None where cookies are always sent, Lax cookies are only sent on same-site request like Strict . However, Lax allows top-level navigation access with a safe HTTP method, like HTTP GET . The cookie will not be sent with cross-domain POST requests or when loading the site in a cross-origin frame, but it will be sent when you navigate to the site via a standard top-level <a href=...> link. |
None | Cookies with this setting will work the same way as cookies work today. Cookies will be able to be used across sites. 💡Note that you need both the None and Secure attributes together. If you just specify None without Secure the cookie will be rejected. Secure ensures that the browser request is sent by a secure (HTTPS) connection. |
🍪 When to use SameSite=Strict
Use when the domain in the URL bar equals the cookie’s domain (first-party) AND the link isn’t coming from a third-party.
Set-Cookie: first_party_var=value; SameSite=Strict
🍪 When to use SameSite=Lax
Use when the domain in the URL bar equals the cookie’s domain (first-party). Note: Third party content (images, iframes, etc.) is allowed.
Set-Cookie: first_party_var=value; SameSite=Lax
🍪 When to use SameSite=None; Secure
Use when you don't need cross-domain limitations.
Set-Cookie: third_party_var=value; SameSite=None; Secure
Common scenarios
When to... | Scenario | Attribute | If you do nothing |
---|---|---|---|
Use SameSite=Strict |
Your website offers banking services or your website needs a very secure environment | Update your SameSite attribute to SameSite=Strict to add a layer of protection from web threats. |
Your site may be susceptible to potential web vulnerabilities and data leaks. |
Use SameSite=Lax |
You have a social community website and you offer embedded chat widgets | Update your SameSite attribute to SameSite=Lax |
You'll be good to go. Chrome's default behavior will be SameSite=Lax . Even if SameSite is not set, the default is still SameSite=Lax |
Use SameSite=None |
Your website offers data analytics services OR your website offers retargeting, advertising and conversion tracking. | Update your SameSite attribute to SameSite=None; Secure to ensure Chrome doesn't reject your third-party cookies. |
Your cookies will no longer work on Feb 4, 2020. |
"Speak to a representative" | You've monetized your website with third-party ad programs OR you're utilizing third-party services like Google Calendar, Cloudflare, Facebook, Twitter, Instagram, LinkedIn, Gravatar, User Tracking services, CRM, reservations plugin, anti-fraud, third-party fonts, image/video hosting and/or payments services. | Speak with the ad program company to ensure they have a plan to update their cookies. You can't update cookies on a domain you don't control. | You may see a decline in the ad revenue you receive and or business engagement. |
Now, set your cookies
Most server-side applications support SameSite
attributes; however, there are a few clients who don't support it (see Known Incompatible Clients).
- For Server-Side Applications: Support for
SameSite=None
in languages, libraries, and frameworks- PHP
- NodeJS
- Python
- Python Flask
- Ruby on Rails
- Recent pull request: https://github.com/rails/rails/pull/28297
- Directly:
document.cookie
Need more help?
Rowan Merewood, Developer Advocate for Chrome, listed a few helpful ways to get help with setting cookies. Keep in mind, this will be a new update so if you run into an issue, it may be the first time anyone has encountered the issue. It is best to just raise the issue, be vocal, and publicly address your concerns because someone else is very likely to encounter the same issue!
- Raise an issue on the
SameSite
examples repo on GitHub. - Post a question on the "samesite" tag on StackOverflow.
- For issues with Chromium's behavior, raise a bug via the [
SameSite
cookies] issue template. - Follow Chrome's progress on the
SameSite
updates page.