Skip to content

Configuring SameSite Cookies in ASP.NET

TLDR

  • The SameSite attribute is used to restrict the sending of third-party cookies to defend against CSRF attacks.
  • There are three SameSite values: None (sent with all requests), Lax (default, sent only with first-party or link requests), and Strict (sent only with first-party requests).
  • In ASP.NET Core, it is recommended to configure this globally via CookiePolicyOptions and implement User-Agent detection for older browsers to handle None value compatibility.
  • In ASP.NET Framework 4.7.2+, global defaults can be set via the httpCookies node in Web.config.
  • The SameSite behavior of ASP.NET_SessionId is affected by the <sessionState> configuration and requires special attention.
  • Browser implementations of SameSite vary; compatibility and testing environments (such as using Incognito mode) should be considered during development.

Core Concepts of SameSite Cookies

SameSite is a standard established by the IETF, designed to restrict the transmission of third-party cookies, thereby reducing the risk of Cross-Site Request Forgery (CSRF).

Explanation of Same-Site Attribute Values

ValueDescription
NoneCookies will be sent with all requests; currently, it must be used with the Secure attribute.
LaxThe default for modern browsers; sent only in first-party contexts or when the user navigates via a link.
StrictCookies are only sent in requests within a first-party context.

When do issues occur?

When an application relies on third-party cookies (such as cross-domain iframe embeds or AJAX requests), setting them to Lax or Strict will prevent the cookies from being read correctly, causing user login sessions to fail or features to malfunction.

WARNING

Browser implementations of SameSite are not entirely consistent. Early versions handled unset SameSite attributes differently, and the None value may not be supported in older browsers, requiring fallback handling via User-Agent detection.


Configuring SameSite Cookies in ASP.NET Core

Global Configuration

Control settings globally via CookiePolicyOptions in Program.cs, and ensure app.UseCookiePolicy() is placed before app.UseAuthorization().

csharp
var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<CookiePolicyOptions>(options => {
    // Set the minimum restriction level
    options.MinimumSameSitePolicy = SameSiteMode.Unspecified;

    // Handle compatibility for 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;
        }
    }
}

If you need to configure specific cookies, you can specify it directly in CookieOptions:

csharp
Response.Cookies.Append("name", "value", new CookieOptions() { 
    SameSite = SameSiteMode.Lax 
});

Configuring SameSite Cookies in ASP.NET Framework

This feature requires Framework 4.7.2 or higher.

Web.config Global Configuration

If an individual cookie does not specify SameSite, the system will use the default value from httpCookies.

xml
<configuration>
  <system.web>
    <httpCookies sameSite="Lax"></httpCookies>
  </system.web>
</configuration>

Compatibility Handling for Older Browsers

Intercept requests in Global.asax.cs and filter out browsers that do not support None:

csharp
protected void Application_BeginRequest(object sender, EventArgs e) {
    HttpApplication application = sender as HttpApplication;
    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++) {
                if (cookies[i].SameSite == SameSiteMode.None) {
                    cookies[i].SameSite = (SameSiteMode)(-1); // Set to Unspecified
                }
            }
        });
    }
}

TIP

The SameSite setting for ASP.NET_SessionId is typically controlled by <sessionState cookieSameSite="..." /> rather than httpCookies. It is recommended to use Incognito mode during testing to prevent existing cookies from affecting test results.


Change Log

  • 2022-10-26 Initial documentation created.