Configuring SameSite Cookies in ASP.NET
TLDR
- The SameSite attribute is used to restrict third-party cookies to defend against CSRF attacks.
- There are three SameSite values:
None(sent with all requests, requiresSecure),Lax(default value, sent only in first-party or link-initiated requests), andStrict(sent only in first-party requests). - In ASP.NET Core, global configuration can be managed via
CookiePolicyOptions, and issues with poorNonesupport in older browsers must be handled. - ASP.NET Framework 4.7.2 and above support
SameSiteconfiguration;Sessionstate requires additional configuration via<sessionState>. - Browser implementations vary significantly; it is recommended to perform compatibility checks based on the
User-Agent.
Core Concepts of SameSite Cookies
SameSite Cookies is a standard established by the IETF, designed to restrict the sending of third-party cookies to defend against Cross-Site Request Forgery (CSRF) attacks.
Explanation of SameSite Attribute Values
When you might encounter this issue: When you need to determine whether a cookie should be sent with cross-site requests.
None: The cookie will be sent in all request scenarios; it must be paired with theSecureattribute in modern environments.Lax: The default value for modern browsers; sent only in first-party contexts or when the user navigates to the original site via a link.Strict: The cookie will only be sent in first-party context requests.
Request Support in Lax Mode
When you might encounter this issue: When an application relies on cookies for login authentication, and users arrive via links from external websites.
| Request Method | Can Cookies be Obtained? |
|---|---|
Link (<a>) | O |
| Form Get | O |
| Form Post | X |
| iframe | X |
| AJAX | X |
| Image | X |
WARNING
Both "Same-Origin Policy" and "SameSite Cookies" are highly dependent on browser implementation, and behavior may differ between versions.
Configuring SameSite Cookies in ASP.NET Core
Global Configuration and Compatibility Handling
When you might encounter this issue: When you need to manage the site-wide cookie policy uniformly and ensure that older browsers do not malfunction due to lack of support for None.
Configure CookiePolicyOptions in Program.cs and use the OnAppendCookie interceptor to handle older browsers:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<CookiePolicyOptions>(options => {
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
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;
}
}
}
// ...other code...
app.UseCookiePolicy(); // Must be placed before UseAuthorizationIndividual Cookie Configuration
When you might encounter this issue: When a specific cookie requires a different SameSite setting than the global policy.
Response.Cookies.Append("name", "value", new CookieOptions() { SameSite = SameSiteMode.Lax });TIP
When SameSiteMode is not set or is specified as Unspecified, the browser will determine the behavior itself.
Configuring SameSite Cookies in ASP.NET Framework
Setting Default Values and Session
When you might encounter this issue: In environments with Framework 4.7.2 or higher, you need to set the global default cookie behavior.
Configure in Web.config:
<configuration>
<system.web>
<!-- If an individual cookie is not set, this will be used as the default -->
<httpCookies sameSite="Lax"></httpCookies>
<!-- Session requires additional configuration -->
<sessionState cookieSameSite="Lax"></sessionState>
</system.web>
</configuration>Compatibility Handling for Older Browsers
When you might encounter this issue: In a Framework environment, you need to dynamically correct cookies for older browsers that do not support None.
Intercept the response headers in Global.asax.cs:
protected void Application_BeginRequest(object sender, EventArgs e) {
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
}
}
});
}
}
}WARNING
When testing the Same-Site behavior of ASP.NET_SessionId, it is recommended to use Incognito mode to avoid interference from previous browsing history.
Change Log
- 2022-10-26 Initial document created.
