Create an account


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Upcoming SameSite Cookie Changes in ASP.NET and ASP.NET Core

#1
Upcoming SameSite Cookie Changes in ASP.NET and ASP.NET Core

<div style="margin: 5px 5% 10px 5%;"><img src="https://www.sickgaming.net/blog/wp-content/uploads/2019/10/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core.jpg" width="58" height="58" title="" alt="" /></div><div><div class="row justify-content-center">
<div class="col-md-4">
<div><img src="https://www.sickgaming.net/blog/wp-content/uploads/2019/10/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core.jpg" width="58" height="58" alt="Avatar" class="avatar avatar-58 wp-user-avatar wp-user-avatar-58 photo avatar-default"></p>
<p>Barry</p>
</div>
</div>
</div>
<div class="entry-meta">
<p>October 18th, 2019</p>
</p></div>
<p><!-- .entry-meta --> </p>
<p>SameSite is a 2016 <a href="https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1" rel="noopener noreferrer" target="_blank">extension to HTTP cookies</a> intended to mitigate cross site request forgery (CSRF). The original design was an opt-in feature which could be used by adding a new SameSite property to cookies. It had two values, Lax and Strict. Setting the value to Lax indicated the cookie should be sent on navigation within the same site, or through GET navigation to your site from other sites. A value of Strict limited the cookie to requests which only originated from the same site. Not setting the property at all placed no restrictions on how the cookie flowed in requests. OpenIdConnect authentication operations (e.g. login, logout), and other features that send POST requests from an external site to the site requesting the operation, can use cookies for correlation and/or CSRF protection. These operations would need to opt-out of SameSite, by not setting the property at all, to ensure these cookies will be sent during their specialized request flows.</p>
<p>Google is now <a href="https://tools.ietf.org/html/draft-west-cookie-incrementalism-00" rel="noopener noreferrer" target="_blank">updating the standard</a> and implementing their proposed changes in an upcoming version of Chrome. The change adds a new SameSite value, “None”, and changes the default behavior to “Lax”. This breaks OpenIdConnect logins, and potentially other features your web site may rely on, these features will have to use cookies whose SameSite property is set to a value of “None”. However browsers which adhere to the original standard and are unaware of the new value have a different behavior to browsers which use the new standard as the SameSite standard states that if a browser sees a value for SameSite it does not understand it should treat that value as “Strict”. This means your .NET website will now have to add user agent sniffing to decide whether you send the new None value, or not send the attribute at all.</p>
<p>.NET will issue updates to change the behavior of its SameSite attribute behavior in .NET 4.7.2 and in .NET Core 2.1 and above to reflect Google’s introduction of a new value. The updates for the .NET Framework will be available on November 19th as an optional update via Microsoft Update and WSUS if you use the “Check for Update” functionality. On December 10th it will become widely available and appear in Microsoft Update without you having to specifically check for updates. .NET Core updates will be available with .NET Core 3.1 starting with preview 1, in November.</p>
<p>.NET Core 3.1 will contain an <a href="https://github.com/aspnet/Announcements/issues/390" rel="noopener noreferrer" target="_blank">updated enum definition</a>, SameSite.Unspecified which will not set the SameSite property.</p>
<p>The OpenIdConnect middleware for Microsoft.Owin v4.1 and .NET Core will be updated at the same time as their .NET Framework and .NET updates, however we cannot introduce the user agent sniffing code into the framework, this must be implemented in your site code. The implementation of agent sniffing will vary according to what version of ASP.NET or ASP.NET Core you are using and the browsers you wish to support.</p>
<p>For ASP.NET 4.7.2 with Microsoft.Owin 4.1.0 agent sniffing can be implemented using <a href="https://docs.microsoft.com/en-us/previous-versions/aspnet/dn800238(v%3Dvs.113)" rel="noopener noreferrer" target="_blank">ICookieManager</a>;</p>
<pre><code>public class SameSiteCookieManager : ICookieManager
{ private readonly ICookieManager _innerManager; public SameSiteCookieManager() : this(new CookieManager()) { } public SameSiteCookieManager(ICookieManager innerManager) { _innerManager = innerManager; } public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options) { CheckSameSite(context, options); _innerManager.AppendResponseCookie(context, key, value, options); } public void DeleteCookie(IOwinContext context, string key, CookieOptions options) { CheckSameSite(context, options); _innerManager.DeleteCookie(context, key, options); } public string GetRequestCookie(IOwinContext context, string key) { return _innerManager.GetRequestCookie(context, key); } private void CheckSameSite(IOwinContext context, CookieOptions options) { if (DisallowsSameSiteNone(context) &amp;&amp; options.SameSite == SameSiteMode.None) { options.SameSite = null; } } public static bool DisallowsSameSiteNone(IOwinContext context) { // TODO: Use your User Agent library of choice here. var userAgent = context.Request.Headers["User-Agent"]; return userAgent.Contains("BrokenUserAgent") || userAgent.Contains("BrokenUserAgent2") }
}
</code></pre>
<p>And then configure OpenIdConnect settings to use the new CookieManager;</p>
<pre><code>app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { // … Your preexisting options … CookieManager = new SameSiteCookieManager(new SystemWebCookieManager())
});
</code></pre>
<p>SystemWebCookieManager will need the .NET 4.7.2 or later SameSite patch installed to work correctly.</p>
<p>For ASP.NET Core you should install the patches and then implement the agent sniffing code within a <a href="https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-3.0#cookie-policy-middleware" rel="noopener noreferrer" target="_blank">cookie policy</a>. For versions prior to 3.1 replace SameSiteMode.Unspecified with (SameSiteMode)(-1).</p>
<pre><code>private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{ if (options.SameSite &gt; SameSiteMode.Unspecified) { var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); // TODO: Use your User Agent library of choice here. if (/* UserAgent doesn’t support new behavior */) { // For .NET Core &lt; 3.1 set SameSite = -1 options.SameSite = SameSiteMode.Unspecified; } }
} public void ConfigureServices(IServiceCollection services)
{ services.Configure&lt;CookiePolicyOptions&gt;(options =&gt; { options.MinimumSameSitePolicy = SameSiteMode.Unspecified; options.OnAppendCookie = cookieContext =&gt; CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); options.OnDeleteCookie = cookieContext =&gt; CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); });
} public void Configure(IApplicationBuilder app)
{ app.UseCookiePolicy(); // Before UseAuthentication or anything else that writes cookies. app.UseAuthentication(); // …
}
</code></pre>
<p>Under testing with the Azure Active Directory team we have found the following checks work for all the common user agents that Azure Active Directory sees that don’t understand the new value.</p>
<pre><code>public&nbsp;static&nbsp;bool&nbsp;DisallowsSameSiteNone(string&nbsp;userAgent)
{
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Cover&nbsp;all&nbsp;iOS&nbsp;based&nbsp;browsers&nbsp;here.&nbsp;This&nbsp;includes:
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;-&nbsp;Safari&nbsp;on&nbsp;iOS&nbsp;12&nbsp;for&nbsp;iPhone,&nbsp;iPod&nbsp;Touch,&nbsp;iPad
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;-&nbsp;WkWebview&nbsp;on&nbsp;iOS&nbsp;12&nbsp;for&nbsp;iPhone,&nbsp;iPod&nbsp;Touch,&nbsp;iPad
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;-&nbsp;Chrome&nbsp;on&nbsp;iOS&nbsp;12&nbsp;for&nbsp;iPhone,&nbsp;iPod&nbsp;Touch,&nbsp;iPad
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;All&nbsp;of&nbsp;which&nbsp;are&nbsp;broken&nbsp;by&nbsp;SameSite=None,&nbsp;because&nbsp;they&nbsp;use&nbsp;the&nbsp;iOS&nbsp;networking&nbsp;stack
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(userAgent.Contains("CPU&nbsp;iPhone&nbsp;OS&nbsp;12")&nbsp;||&nbsp;userAgent.Contains("iPad;&nbsp;CPU&nbsp;OS&nbsp;12"))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;
&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Cover&nbsp;Mac&nbsp;OS&nbsp;X&nbsp;based&nbsp;browsers&nbsp;that&nbsp;use&nbsp;the&nbsp;Mac&nbsp;OS&nbsp;networking&nbsp;stack.&nbsp;This&nbsp;includes:
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;-&nbsp;Safari&nbsp;on&nbsp;Mac&nbsp;OS&nbsp;X.
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;This&nbsp;does&nbsp;not&nbsp;include:
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;-&nbsp;Chrome&nbsp;on&nbsp;Mac&nbsp;OS&nbsp;X
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Because&nbsp;they&nbsp;do&nbsp;not&nbsp;use&nbsp;the&nbsp;Mac&nbsp;OS&nbsp;networking&nbsp;stack.
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(userAgent.Contains("Macintosh;&nbsp;Intel&nbsp;Mac&nbsp;OS&nbsp;X&nbsp;10_14")&nbsp;&amp;&amp;&nbsp; userAgent.Contains("Version/") &amp;&amp; userAgent.Contains("Safari"))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;
&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Cover&nbsp;Chrome&nbsp;50-69,&nbsp;because&nbsp;some&nbsp;versions are&nbsp;broken&nbsp;by&nbsp;SameSite=None,&nbsp; // and&nbsp;none in this range require&nbsp;it.
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Note:&nbsp;this covers&nbsp;some&nbsp;pre-Chromium&nbsp;Edge&nbsp;versions,&nbsp; // but pre-Chromium&nbsp;Edge&nbsp;does&nbsp;not&nbsp;require&nbsp;SameSite=None.
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(userAgent.Contains("Chrome/5")&nbsp;||&nbsp;userAgent.Contains("Chrome/6"))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;
&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false;
}
</code></pre>
<p>This browser list is by no means canonical and you should validate that the common browsers and other user agents your system supports behave as expected once the update is in place.</p>
<p>Chrome 80 is scheduled to <a href="https://www.chromium.org/updates/same-site" rel="noopener noreferrer" target="_blank">turn on the new behavior</a> in February or March 2020, including a temporary mitigation added in Chrome 79 Beta. If you want to test the new behavior without the mitigation use Chromium 76. Older versions of Chromium are <a href="http://www.chromium.org/getting-involved/download-chromium" rel="noopener noreferrer" target="_blank">available for download</a>.</p>
<p>If you cannot update your framework versions by the time Chrome turns the new behavior in early 2020 you may be able to change your OpenIdConnect flow to a Code flow, rather than the default implicit flow that ASP.NET and ASP.NET Core uses, but this should be viewed as a temporary measure.</p>
<p>We strongly encourage you to download the updated .NET Framework and .NET Core versions when they become available in November and start planning your update before Chrome’s changes are rolled out.</p>
<div class="authorinfoarea">
<div><img src="https://www.sickgaming.net/blog/wp-content/uploads/2019/10/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core-1.jpg" width="96" height="96" alt="Avatar" class="avatar avatar-96 wp-user-avatar wp-user-avatar-96 photo avatar-default"></div>
</p></div>
</div>


https://www.sickgaming.net/blog/2019/10/...-net-core/
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

Forum software by © MyBB Theme © iAndrew 2016