6

In order to avoid CSRF (Cross-site request forgery) most browsers are (since late 2019) automatically considering that any cookie that does not explicitly define SameSite attribute will be considered as Lax, instead of None which was the previous default.

And more recently (Feb 2020, since Chrome 80) browsers are also ignoring cookies which define SameSite=None and are not secure.

How can I change my session cookies to be automatically changed to None (to keep my SSO integrations working) in my Web.config?

drizin
  • 1,737
  • 1
  • 18
  • 44

1 Answers1

13

EDIT of 2020-08-03: Chrome 85 doesn't allow insecure SameSite=None cookies
I've updated code accordingly: 1) only apply SameSite=None if connection is https; 2) only apply Secure; if connection is https; 3) remove SameSite=None if it's http and samesite was added by the attributes (rewrite rules)

Original response:

This is a pure web.config solution which:

  • Defines that session cookies should be rendered with SameSite=None
  • Appends SameSite=None to any cookie which does not explicitly defines SameSite attribute (using methods that work in all versions of framework, in the worst case if some attribute is not accepted you can just remove it)
  • Appends Secure attribute to any cookie which is not yet secure (as long as it's https request)
  • Removed SameSite=None if it was applied by previous rules and it's not valid due to lack of https
<!-- This sets ASP.NET_SessionId cookie to SameSite=None, 
avoiding the default of current frameworks which is LAX -->
<system.web>

<!-- in newer framework versions you have to change the samesite 
level like by changing this default level -->
<!-- in old versions these attributes might not be allowed
and in case (if they don't work) just ignore/skip them -->

<sessionState cookieSameSite="None" />
<httpCookies sameSite="None"/>
<authentication mode="Forms">
    <forms ..... cookieSameSite="None" />
</authentication>

...
</system.web>
...
<system.webServer>
<rewrite>
   <outboundRules>
    <!-- for old versions the only solution is to intercept/modify cookies -->

    <!-- Add "SameSite=None" to any cookie which does NOT have it yet -->
    <!-- currently this only works for secure https cookies -->
    <rule name="Add SameSite">
     <conditions>
      <add input="{RESPONSE_Set_Cookie}" pattern="." />
      <add input="{RESPONSE_Set_Cookie}" pattern="; SameSite=None" negate="true" />
      <add input="{HTTPS}" pattern="on" ignoreCase="true" />
     </conditions>
     <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
     <action type="Rewrite" value="{R:0}; SameSite=None" />
    </rule>

    <!-- Add "Secure" to any cookie which does NOT have it yet, as long as it's HTTPS request or else a secure cookie would just be ignored -->
    <rule name="Add Secure">
     <conditions>
        <add input="{RESPONSE_Set_Cookie}" pattern="." />
        <add input="{RESPONSE_Set_Cookie}" pattern="; Secure" negate="true" />
        <add input="{HTTPS}" pattern="on" ignoreCase="true" />
     </conditions>
     <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
     <action type="Rewrite" value="{R:0}; Secure" />
    </rule>

    <!-- If samesite was set to none by cookieSameSite="None", -->
    <!-- remove it for non-https requests (currently only works for https) -->
    <rule name="No SameSite For HTTP">
     <conditions>
      <add input="{HTTPS}" pattern="off" ignoreCase="true" />
     </conditions>
     <match serverVariable="RESPONSE_Set_Cookie" pattern="(.*);(\s*)SameSite=None" />
     <action type="Rewrite" value="{R:1}" />
    </rule>


   </outboundRules>
</rewrite>
</system.webServer>

If you don't use the the <sessionState cookieSameSite="None" /> some newer ASP.NET Framework versions will by default render a SameSite=Lax. And if you just had the rewrite rules adding SameSite=None to all cookies you would get the SameSite attribute twice, which according to my tests work in SOME browsers like Chrome and Firefox (which will use the last occurrence of the SameSite attribute) but won't work in some like Edge (which uses the first occurrence of the attribute).

Since this first tag <sessionState cookieSameSite="None" /> will automatically set SameSite=None but will not automatically add Secure attribute, I've configured SameSite=None and Secure as independent rules. If I had it all in a single rule I would end up with duplicated attribute SameSite=None, which could break browsers (as explained above it's invalid and browsers may handle this inconsistently).

The Secure is only added if it's HTTPS request, so if you're still accepting HTTP connections your session cookies won't have the Secure added, which would make browsers ignore your cookie (and session wouldn't work at all). If you're behind a load balancer or reverse proxy you should use the HTTP_X_FORWARDED_PROTO attribute

Last, there's a bug in some versions of Safari in which the browser doesn't understand SameSite=None and treat it as SameSite=Strict. So for those specific versions you might decide not to render SameSite=None, although if not specified the default is still SameSite=Lax level, which might not be what you need (haven't found a solution for that).

drizin
  • 1,737
  • 1
  • 18
  • 44
  • 1
    It should be not – Doctor.Who. Mar 23 '20 at 04:10
  • I am using .NET framework 4.6.1, it seems it is not marked as Secured yet even using the rewrite. Do you have any idea? – Michieru Mar 27 '20 at 14:48
  • 1
    @Michieru in localhost with http? Or in production with https? Secure is supposed to only work in HTTPS, that's why I added a restriction that secure is added only when HTTPS=TRUE. You can remove that rule if you want. For example if you're using a reverse proxy (which listens https but redirects to your IIS in http) you should remove it. – drizin Mar 27 '20 at 16:53
  • See solution for agent-specific setting here: https://stackoverflow.com/a/60357945/198953 – cederlof Apr 03 '20 at 10:54
  • For some reason I cannot get this working. IIS is automatically adding attribute SameSite=Lax to authentication cookie and the changes to web.config don't do anything on IIS version 10.0.14393.0. (Windows server 2016). However, with IIS 8.5.9600.16384 (Windows Server 2012 R2) these changes are working. What could be wrong? Could security update KB4537764 on Win Server 2016 affect this? Help appreciated. – Markku Rintala Apr 06 '20 at 12:02
  • @MarkkuRintala have you added `` ? – drizin Apr 06 '20 at 16:16
  • Yes, I did. After some more searching in the internet I found this: https://port135.com/2020/02/13/changes-to-the-samesite-cookie/. There writer suggested to add cookieSameSite="None" also to . That worked for me. That article gives also essential information on latest Windows updates that are related to the SameSite cookie. Maybe I should write a new answer or you @drizin could update yours. – Markku Rintala Apr 07 '20 at 07:06
  • @MarkkuRintala I've just updated my answer. Thanks! – drizin Apr 07 '20 at 17:24
  • Thanks a lot, that saved my life. – Muzaffer Galata Sep 11 '20 at 19:27
  • 1
    Worked for me, Thank you! In the second section of rules, the add-statements are not inside a block. – Bernhard Krenz Nov 26 '20 at 12:13
  • @drizin it is still not working : https://stackoverflow.com/questions/71766217/asp-net-webforms-application-cookies-are-not-working-anymore-within-canvas-fac – Furkan Gözükara Apr 06 '22 at 12:45