Configuring SameSite Cookies in ASP.NET
SameSite Cookies
SameSite Cookies is a draft standard established by the IETF in 2016, aimed at restricting third-party cookies to prevent web applications from Cross-Site Request Forgery (CSRF) attacks. It was updated in 2019.
In cybersecurity, you often hear about a similar concept: the "Same-Origin Policy." This is a mechanism that restricts interactions between a browser's Document and Resources (such as images). When the protocol, host, and port of two URLs are identical, they are considered to be from the same origin. In most cases, you are only allowed to read your own resources. For specific implementation details, please refer to MDN Same-Origin.
The definition of "Same-Site" is broader than "Same-Origin." Since there is no official documentation, you can refer to this article for specific differences: Same-Site and Same-Origin.
Same-Site Values
| Value | Description |
|---|---|
| None | Cookies are sent in all request contexts. Formerly the default, it now requires Secure. |
| Lax | Cookies are sent only in first-party contexts or when the user navigates to the origin site via a link. This is the current default for modern browsers. |
| Strict | Cookies are sent only in first-party contexts. |
Lax Support for Third-Party Site Requests
| Request Method | Code Example | Can obtain Cookies? |
|---|---|---|
| Link | <a href="..."></a> | O |
| Prerender | <link ref="prerender" hre="..."></a> | O |
| Form Get | <form method="GET" action="..."></form> | O |
| Form Post | <form method="POST" action="..."></form> | X |
| iframe | <iframe src="..."></iframe> | X |
| AJAX | $.get("..."); | X |
| Image | <img src="..."> | X |
Cookie Types
| Type | Definition | Common Usage |
|---|---|---|
| First-Party Cookie | Cookies that match the domain of the current site are called First-Party Cookies. | Recording login information or preference settings. |
| Third-Party Cookie | Cookies that do not match the domain of the current site are called Third-Party Cookies. | Recording browsing data for advertising and analytics. |
TIP
The "second party" refers to the Client, so there is no such thing as a "Second-Party Cookie." There is a similar term called "Second-Party Data," but it is an unrelated concept.
Workflow
- When the Server responds to a Client's request, it uses
Set-Cookieto pass a Response Cookie. At this point, the Same-Site value is added to the content, for example:Set-Cookie: {Cookie Name}={Cookie Value}; SameSite={SameSite Value}. When the Client stores this cookie, it also records the Same-Site value. We refer to this server as Site A, and the stored cookie as the A Cookie. - When subsequent requests are made to Site A via links, images, or iframes from Site B, the request will determine whether to include the A Cookie based on the SameSite value previously recorded by the A Cookie.
For example, suppose the A Cookie contains login information for Site A and the Same-Site value is Strict. When navigating from Site B to Site A, because Strict does not send cookies to third-party sites, the login information cannot be retrieved, resulting in an unauthenticated state.
WARNING
- Both the "Same-Origin Policy" and "SameSite Cookies" rely on browser implementation, so the effects may vary across different browser versions, especially for "SameSite Cookies."
- The initial version of Same-Site did not have a
Nonevalue; if Same-Site was not set, it acted like the currentNone. However, some browsers treated it asStrict. It wasn't untilNonewas defined that it became the default, and later, the default was changed toLax.
References:
- Samesite cookie explained
- Chrome 80+ rules adjustment for third-party cookies (default SameSite=Lax)
- Revisiting Same-Origin Policy: Impact of SameSite settings on Cookies and considerations
Configuring SameSite Cookies in ASP.NET Core
Global Configuration
Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add the following code
builder.Services.Configure<CookiePolicyOptions>(options => {
// Set the minimum level: Strict > Lax > None > Unspecified
// If MinimumSameSitePolicy is set to Lax, but CookieOptions.SameSite is set to None, it will ultimately use Lax
// If MinimumSameSitePolicy is set to Lax, but CookieOptions.SameSite is set to Strict, it will ultimately use Strict
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
// Only implement if you need to support older browsers
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
void CheckSameSite(HttpContext httpContext, CookieOptions options) {
if (options.SameSite == SameSiteMode.None) {
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (DisallowsSameSiteNone(userAgent)) {
options.SameSite = SameSiteMode.Unspecified;
}
}
}
bool DisallowsSameSiteNone(string userAgent) {
// Use userAgent to identify the browser version and return true for browsers that do not yet support None
// Since there are too many browser versions and the official documentation is not fully implemented, specific implementation is not listed here
return true;
}
// ...other code...
app.UseCookiePolicy(); // Add this line, and it must be placed before UseAuthorization
app.UseAuthorization();
app.MapRazorPages();
app.Run();Individual Cookie Configuration
// CookieOptions.SameSite defaults to Unspecified
Response.Cookies.Append("name", "value", new CookieOptions() { SameSite = SameSiteMode.Lax });TIP
- If SameSiteMode is not set or is specified as
Unspecified, Same-Site will not be set on the cookie, leaving it to the Client to decide. - For the internal implementation of Same-Site in .NET Core, you can refer to the ResponseCookiesWrapper source code.
MSDN Documentation
Work with SameSite cookies in ASP.NET Core
Configuring SameSite Cookies in ASP.NET Framework
Relevant APIs are supported from Framework 4.7.2 and above.
Setting Defaults
- If an individual cookie does not have Same-Site set, this configuration will be used as the default.
- Although Session is stored in a cookie by default, testing shows it is not affected by
<httpCookies sameSite />, but rather by the<sessionState cookieSameSite />setting. If not set, it defaults toLax.
WARNING
- If
ASP.NET_SessionIddoes not have<sessionState cookieSameSite />set, it defaults toLax. This is the result of testing on Framework 4.8.1; results may vary across different Framework versions. - When testing the Same-Site value of
ASP.NET_SessionId, it is best to use Incognito mode; otherwise, it may be affected by previously opened pages.
Web.config
<configuration>
<system.web>
<!--If an individual cookie does not have Same-Site set, this configuration will be used as the default-->
<httpCookies sameSite="Lax"></httpCookies>
</system.web>
</configuration>Individual Cookie Configuration
HttpCookie cookie = new HttpCookie("name");
cookie.Value = "value";
cookie.SameSite = SameSite.Lax; // Set Same-Site
Response.Cookies.Add(cookie);TIP
Cookie Same-Site values are retrieved in the following order: HttpCookie.SameSite => <httpCookies sameSite /> => Not set.
Compatibility with Older Browsers
Global.asax.cs
protected void Application_BeginRequest(object sender, EventArgs e) {
FilterSameSiteNoneForIncompatibleUserAgents(sender);
}
public static void FilterSameSiteNoneForIncompatibleUserAgents(object sender) {
HttpApplication application = sender as HttpApplication;
if (application != null) {
var userAgent = application.Context.Request.UserAgent;
if (DisallowsSameSiteNone(userAgent)) {
HttpContext.Current.Response.AddOnSendingHeaders(context => {
var cookies = context.Response.Cookies;
for (var i = 0; i < cookies.Count; i++) {
var cookie = cookies[i];
if (cookie.SameSite == SameSiteMode.None) {
cookie.SameSite = (SameSiteMode)(-1); // Unspecified
}
}
});
}
}
}
public static bool DisallowsSameSiteNone(string userAgent) {
// Use userAgent to identify the browser version and return true for browsers that do not yet support None
// Since there are too many browser versions and the official documentation is not fully implemented, specific implementation is not listed here
return true;
}MSDN Documentation
Work with SameSite cookies in ASP.NET
Revision History
- 2022-10-26 Initial document created.
