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 being subjected to Cross-Site Request Forgery (CSRF) attacks. It was updated in 2019.
In security, you often hear about a similar concept: "Same-Origin Policy". It is a mechanism used to restrict 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, and in most cases, they are only allowed to read their own resources. For specific implementation details, please refer to MDN Same-Origin.
The definition of Same-Site is broader than that of Same-Origin. Since there is no official documentation explaining this, you can refer to this article for specific differences: Same-Site and Same-Origin.
Same-Site Values
| Value | Description |
|---|---|
| None | The cookie will be sent in all request contexts. Formerly the default value, it now requires Secure. |
| Lax | Cookies are only sent in first-party contexts or when the user navigates to the origin site via a link. This is the current default for browsers. |
| Strict | The cookie will only be sent in a first-party context. |
Lax Support for Third-Party Site Requests
| Request Method | Code Example | Can Cookies be retrieved? |
|---|---|---|
| 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 Use Cases |
|---|---|---|
| First-Party Cookie | Cookies that match the domain of the current website are called First-Party Cookies. | Recording login information or preference settings. |
| Third-Party Cookie | Cookies that do not match the domain of the current website 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", which is an unrelated concept.
Workflow
- When the Server responds to a Client's Request, it uses
Set-Cookieto pass the 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 Website A, and the stored cookie as the A Cookie. - When a subsequent Request is made to Website A via a link, image, or iframe on Website B, the Request will include or exclude the A Cookie based on the SameSite value previously recorded.
For example, suppose the A Cookie contains login information for Website A, and its Same-Site value is Strict. When navigating from Website B to Website A, because Strict does not send cookies to third-party sites, the login information cannot be retrieved, resulting in an unauthenticated state.
WARNING
- Both "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 the
Nonevalue; instead, not setting a Same-Site attribute was treated as the currentNone. However, some browsers treated it asStrict. It was only afterNonewas defined that it became the default, and later the default was changed toLax.
Reference Articles:
- Samesite cookie explained
- Chrome 80+ rules for third-party cookies (default SameSite=Lax)
- Revisiting Same-Origin Policy: The impact of SameSite settings on Cookies and precautions
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, Lax will be used.
// If MinimumSameSitePolicy is set to Lax, but CookieOptions.SameSite is set to Strict, Strict will be used.
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 browser versions 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
// The default value for CookieOptions.SameSite is 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 file.
MSDN Documentation
Work with SameSite cookies in ASP.NET Core
Configuring SameSite Cookies in ASP.NET Framework
APIs are supported in Framework 4.7.2 and above.
Setting Default Values
- If an individual cookie does not have a Same-Site setting, this configuration will be used.
- 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 in Framework 4.8.1; results may vary in 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 a Same-Site setting, this configuration will be used-->
<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 browser versions 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
Change Log
- 2022-10-26 Initial document created.