Configuring cookie SameSite mode
SameSite is an attribute that is used to control browser behavior when sending cookies. Using the attribute, you can configure whether cookies are sent along with requests initiated by third party websites. This is mainly useful for mitigating cross-site request forgery attacks.
The SameSite attribute enforces three levels of strictness:
- Strict – cookies marked as Strict are only sent as part of same-site requests. In other words, each cookie is only sent if the request URL matches the domain set in the cookie.
- Lax – cookies marked as Lax are sent as part of same-site requests and during requests that cause top-level navigation (change the URL in the browser’s address bar) to the cookie’s domain from a third-party site.
- None – None enforces no cross-domain restrictions when sending cookies. However, each cookie needs to be paired with the Secure attribute, which ensures it will only be sent if transmitted over a secure channel (typically using HTTPS). SameSite=None cookies without the Secure attribute are not included in regular requests.
For an in-depth explanation of the SameSite attribute, its associated modes, and resulting browser behavior, refer to the following article: SameSite cookies explained
Consequences for Xperience sites
An Xperience site consists of two applications – a front-end site used to present content and a corresponding administration application used to manage and configure the system. For the most part, both applications act completely independently and only communicate via a shared database. However, the page preview mode feature, used by the Xperience administration to preview content from the live site application, relies on certain cookies transmitted between the two applications to work correctly.
To use the preview mode and other features that build upon this functionality (such as the page builder), you need to ensure the system and its hosting environment conform to the requirements imposed by SameSite. Depending on your environment, you may need to:
- Adjust the configuration of your hosting environment to ensure cookies between the two applications are sent correctly.
- Accordingly configure the SameSite mode for any custom cookies used in your projects.
There are two main hosting configurations to consider, determined by the number of domains used to host your live site and administration. Each configuration comes with specific requirements summarized by the following diagram:
See the following sections for details:
Single-domain environment
By default, the system sends all registered cookies using SameSite=Lax. If both the live site and administration applications run on a single domain, no additional configuration is necessary.
In the context of SameSite, a single domain is classified as:
- Any unique name registered directly under a top-level domain. For example, sub.domain.com and domain.com are recognized as belonging to a single domain. However, domain.com and microsoft.com are recognized as different domains. The same applies to port numbers – domain.com:8080 and domain.com:8081 are classified as different.
- A domain registered directly under a single public suffix. Such suffixes are aggregated into lists used by browsers when determining request origin. The most popular list of public suffixes used by the majority of browsers is maintained by the Mozilla Corporation and can be found here. For example, sub.mysite.github.io and mysite.github.io are recognized as belonging to a single domain (github.io is a known public suffix). However, mysite.github.io and yoursite.github.io are recognized as different domains.
Requests targeting domains that do not fulfill these specified criteria are classified as cross-domain (and require appropriate SameSite configuration).
Custom cookies
This section describes the behavior of default system cookies. Custom cookies used by the application are completely under your control. See Working with cookies to learn how to set cookies with the desired SameSite attributes using the Xperience API.
If you need to change the default SameSite mode for specific system cookies (for example, you wish to enforce the Strict mode), see changing the SameSite of Xperience cookies.
Multi-domain environment
In cases where the live site and administration applications are hosted on separate domains, requests between the two applications are classified as cross-domain. As a result, system cookies must be sent using SameSite=None and paired with the Secure attribute.
If your browser blocks third-party cookies, the system cookies must also be paired with the Partitioned attribute.
Cookies are essential for all system features based on the preview mode, such as the page builder or page preview links. Under preview mode, the Xperience administration communicates directly with the live site application via special virtual context requests (containing contextual information about the requested page and validation hashes), which rely on specific cookies on the client.
Note: If your site does not use the preview mode or any dependent features, you do not need to configure system cookies in any way.
Enable sending of application cookies under SameSite=None by adding the SetAdminCookiesSameSiteNone call after IServiceCollection.AddKentico in the ConfigureServices method of your application’s startup class:
public void ConfigureServices(IServiceCollection services)
{
services.AddKentico()
// Required when hosting the administration application and the live site on different domains.
// Sets the 'SameSite' attribute of system cookies to 'None' and pairs them with the 'Secure' and 'Partitioned' attributes
// when sent under preview mode. Both applications also need to use a secure connection (HTTPS)
// to ensure the cookies are not rejected.
.SetAdminCookiesSameSiteNone();
...
}
Enable sending of application cookies under SameSite=None by adding the CMSAdminCookiesSameSiteNone key with the true value to your MVC application’s web.config file:
<appSettings>
<!--
Required when hosting the administration application and the live site on different domains.
Sets the 'SameSite' attribute of system cookies to 'None' and pairs them with the 'Secure' and 'Partitioned' attributes when sent
under preview mode. Both applications also need to use a secure connection (HTTPS) to ensure the cookies are not rejected.
-->
<add key="CMSAdminCookiesSameSiteNone" value="true" />
</appSettings>
Additionally, both the applications that comprise a single Xperience site need to use a secure connection (HTTPS) to ensure the cookies are not rejected on the client.
Custom cookies
This section describes the behavior of default system cookies. Custom cookies used by the application are completely under your control. See Working with cookies to learn how to set cookies with the desired SameSite attributes using the Xperience API.
If you need to change the default SameSite mode for specific system cookies (for example, you wish to enforce the Strict mode), see changing the SameSite of Xperience cookies.
Changing the SameSite of Xperience cookies
You can modify cookies by assigning a delegate to the OnAppendCookie property of CookiePolicyOptions. The delegate is invoked for each cookie added to requests. For this approach to work, the cookie policy middleware (UseCookiePolicy) needs to be registered in the application’s middleware pipeline.
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<CookiePolicyOptions>(o =>
{
o.OnAppendCookie = c =>
{
// Sets the 'SameSite' attribute of the CMSShoppingCart cookie to 'None' and pairs it with the 'Secure' attribute.
// Note that the request needs to be sent encrypted (typically using HTTPS) when using this configuration.
// Otherwise, the cookie is discarded by the browser.
if (c.CookieName == "CMSShoppingCart")
{
c.CookieOptions.SameSite = SameSiteMode.None;
c.CookieOptions.Secure = true;
}
};
});
}
You can register a custom handler for the PreSendRequestHeaders event. Inside the handler, you can access and modify system cookies sent as part of each request via the CMSHttpContextclass.
The following example uses a custom code-only module to register a new handler for the PreSendRequestHeaders event. The handler sets the SameSite mode of a selected cookie to None and adds the Secure attribute.
using System;
using CMS;
using CMS.Base;
using CMS.DataEngine;
using CMS.Helpers;
// Registers the custom module into the system
[assembly: RegisterModule(typeof(RegisterHandlers))]
public class RegisterHandlers : Module
{
public RegisterHandlers()
: base("RegisterHandlers")
{
}
// Contains initialization code that is executed when the application starts
protected override void OnInit()
{
base.OnInit();
// Registers an event handler for the PreSendRequestHeaders event
RequestEvents.PreSendRequestHeaders.Execute += ModifySameSiteCookieMode;
}
public void ModifySameSiteCookieMode(object sender, EventArgs e)
{
// Sets the 'SameSite' attribute of the CMSShoppingCart cookie to 'None' and pairs it with the 'Secure' attribute
// Note that the request needs to be sent encrypted (typically using HTTPS) when using this configuration.
// Otherwise, the cookie is discarded by the browser.
CMSHttpContext.Current.Request.Cookies["CMSShoppingCart"].SameSite = CMS.Base.SameSiteMode.None;
CMSHttpContext.Current.Request.Cookies["CMSShoppingCart"].Secure = true;
}
}