forked from dotnet/AspNetCore.Docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc * Update SameSite doc
- Loading branch information
1 parent
fdb7fdf
commit 94808ea
Showing
8 changed files
with
656 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
--- | ||
title: ASP.NET Core 2.1 MVC SameSite cookie sample | ||
author: rick-anderson | ||
description: ASP.NET Core 2.1 MVC SameSite cookie sample | ||
monikerRange: '>= aspnetcore-2.1 < aspnetcore-3.0' | ||
ms.author: riande | ||
ms.custom: mvc | ||
ms.date: 12/03/2019 | ||
uid: security/samesite/mvc21 | ||
--- | ||
|
||
# ASP.NET Core 2.1 MVC SameSite cookie sample | ||
|
||
ASP.NET Core 2.1 has built-in support for the [SameSite](https://www.owasp.org/index.php/SameSite) attribute, but it was written to the original standard. The [patched behavior](https://github.com/dotnet/aspnetcore/issues/8212) changed the meaning of `SameSite.None` to emit the sameSite attribute with a value of `None`, rather than not emit the value at all. If you want to not emit the value you can set the `SameSite` property on a cookie to -1. | ||
|
||
## <a name="sampleCode"></a>Writing the SameSite attribute | ||
|
||
Following is an example of how to write a SameSite attribute on a cookie: | ||
|
||
```c# | ||
var cookieOptions = new CookieOptions | ||
{ | ||
// Set the secure flag, which Chrome's changes will require for SameSite none. | ||
// Note this will also require you to be running on HTTPS | ||
Secure = true, | ||
|
||
// Set the cookie to HTTP only which is good practice unless you really do need | ||
// to access it client side in scripts. | ||
HttpOnly = true, | ||
|
||
// Add the SameSite attribute, this will emit the attribute with a value of none. | ||
// To not emit the attribute at all set the SameSite property to (SameSiteMode)(-1). | ||
SameSite = SameSiteMode.None | ||
}; | ||
|
||
// Add the cookie to the response cookie collection | ||
Response.Cookies.Append(CookieName, "cookieValue", cookieOptions); | ||
``` | ||
|
||
## Setting Cookie Authentication and Session State cookies | ||
|
||
Cookie authentication, session state and [various other components](https://docs.microsoft.com/aspnet/core/security/samesite?view=aspnetcore-2.1) set their sameSite options via Cookie options, for example | ||
|
||
```c# | ||
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) | ||
.AddCookie(options => | ||
{ | ||
options.Cookie.SameSite = SameSiteMode.None; | ||
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; | ||
options.Cookie.IsEssential = true; | ||
}); | ||
|
||
services.AddSession(options => | ||
{ | ||
options.Cookie.SameSite = SameSiteMode.None; | ||
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; | ||
options.Cookie.IsEssential = true; | ||
}); | ||
``` | ||
|
||
In the preceding code, both cookie authentication and session state set their sameSite attribute to `None`, emitting the attribute with a `None` value, and also set the Secure attribute to true. | ||
|
||
### Run the sample | ||
|
||
If you run the [sample project](https://github.com/blowdart/AspNetSameSiteSamples/tree/master/AspNetCore21MVC), load your browser debugger on the initial page and use it to view the cookie collection for the site. To do so in Edge and Chrome press `F12` then select the `Application` tab and click the site URL under the `Cookies` option in the `Storage` section. | ||
|
||
![Browser Debugger Cookie List](BrowserDebugger.png) | ||
|
||
You can see from the image above that the cookie created by the sample when you click the "Create SameSite Cookie" button has a SameSite attribute value of `Lax`, matching the value set in the [sample code](#sampleCode). | ||
|
||
## <a name="interception"></a>Intercepting cookies | ||
|
||
In order to intercept cookies, to adjust the none value according to its support in the user's browser agent you must use the `CookiePolicy` middleware. This must be placed into the http request pipeline **before** any components that write cookies and configured within `ConfigureServices()`. | ||
|
||
To insert it into the pipeline use `app.UseCookiePolicy()` in the `Configure(IApplicationBuilder, IHostingEnvironment)` method in [Startup.cs](https://github.com/blowdart/AspNetSameSiteSamples/blob/master/AspNetCore21MVC/Startup.cs). For example: | ||
|
||
```c# | ||
public void Configure(IApplicationBuilder app, IHostingEnvironment env) | ||
{ | ||
if (env.IsDevelopment()) | ||
{ | ||
app.UseDeveloperExceptionPage(); | ||
} | ||
else | ||
{ | ||
app.UseExceptionHandler("/Home/Error"); | ||
app.UseHsts(); | ||
} | ||
|
||
app.UseHttpsRedirection(); | ||
app.UseStaticFiles(); | ||
app.UseCookiePolicy(); | ||
app.UseAuthentication(); | ||
app.UseSession(); | ||
|
||
app.UseMvc(routes => | ||
{ | ||
routes.MapRoute( | ||
name: "default", | ||
template: "{controller=Home}/{action=Index}/{id?}"); | ||
}); | ||
} | ||
``` | ||
|
||
Then in the `ConfigureServices(IServiceCollection services)` configure the cookie policy to call out to a helper class when cookies are appended or deleted. For example: | ||
|
||
```c# | ||
public void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.Configure<CookiePolicyOptions>(options => | ||
{ | ||
options.CheckConsentNeeded = context => true; | ||
options.MinimumSameSitePolicy = SameSiteMode.None; | ||
options.OnAppendCookie = cookieContext => | ||
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); | ||
options.OnDeleteCookie = cookieContext => | ||
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); | ||
}); | ||
} | ||
|
||
private void CheckSameSite(HttpContext httpContext, CookieOptions options) | ||
{ | ||
if (options.SameSite == SameSiteMode.None) | ||
{ | ||
var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); | ||
if (SameSite.BrowserDetection.DisallowsSameSiteNone(userAgent)) | ||
{ | ||
options.SameSite = (SameSiteMode)(-1); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
The helper function `CheckSameSite(HttpContext, CookieOptions)`: | ||
|
||
* Is called when cookies are appended to the request or deleted from the request. | ||
* Checks to see if the `SameSite` property is set to `None`. | ||
* If `SameSite` is set to `None` and the current user agent is known to not support the | ||
none attribute value. The check is done using the [SameSiteSupport](https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/security/samesite/sample/snippets/SameSiteSupport.cs) class: | ||
* Sets `SameSite` to not emit the value by setting the property to `(SameSiteMode)(-1)` | ||
|
||
## Targeting .NET Framework | ||
|
||
ASP.NET Core and System.Web (ASP.NET Classic) have independent implementations of SameSite. The SameSite KB patches for .NET Framework are not required if using ASP.NET Core nor does the System.Web SameSite minimum framework version requirement (.NET 4.7.2) apply to ASP.NET Core. | ||
|
||
ASP.NET Core on .NET requires updating nuget package dependencies to get the appropriate fixes. | ||
|
||
To get the ASP.NET Core changes for .NET Framework ensure that you have a direct reference to the patched packages and | ||
versions (2.1.14 or later 2.1 versions). | ||
|
||
```xml | ||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.1.14" /> | ||
<PackageReference Include="Microsoft.AspNetCore.CookiePolicy" Version="2.1.14" /> | ||
``` | ||
|
||
### More Information | ||
|
||
[Chrome Updates](https://www.chromium.org/updates/same-site) | ||
[ASP.NET Core SameSite Documentation](https://docs.microsoft.com/aspnet/core/security/samesite?view=aspnetcore-2.1) | ||
[ASP.NET Core 2.1 SameSite Change Announcement](https://github.com/dotnet/aspnetcore/issues/8212) |
Oops, something went wrong.