49

I was surfing the web and found article Preventing CSRF with the same-site cookie attribute.

As on link maintain We need to add Set-Cookie header.

Set-Cookie: key=value; HttpOnly; SameSite=strict

Now My Question is, I want to set this in my ASP.NET site in all Cookies and Authentication Cookie. I tried to set this using header from IIS but someone says this is wrong way implementation.

I have also tried below.

HttpCookie newAuthenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName
                    , FormsAuthentication.Encrypt(newAuthenticationTicket))
                {
                    HttpOnly = true
                };
newAuthenticationCookie.Values.Add("SameSite", "strict");

But it seems like not helping me.

Please suggest me a better way to do this.

Thanks.

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
imlim
  • 1,607
  • 1
  • 14
  • 21

8 Answers8

59

After Deep review on HttpCookie Source it's confirm that we cannot do this with the code, as there is no way to add extra attribute on Cookie and class is marked as sealed.

But still anyhow I manage solution by modifying web.config as below.

<rewrite>
  <outboundRules>
    <rule name="Add SameSite" preCondition="No SameSite">
      <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
      <action type="Rewrite" value="{R:0}; SameSite=strict" />
      <conditions>
      </conditions>
    </rule>
    <preConditions>
      <preCondition name="No SameSite">
        <add input="{RESPONSE_Set_Cookie}" pattern="." />
        <add input="{RESPONSE_Set_Cookie}" pattern="; SameSite=strict" negate="true" />
      </preCondition>
    </preConditions>
  </outboundRules>
</rewrite>

This add SameSite=strict on each Set-Cookie.

Hooman Bahreini
  • 14,480
  • 11
  • 70
  • 137
imlim
  • 1,607
  • 1
  • 14
  • 21
  • .NET has now support for this, check my answer below – tif May 24 '18 at 11:26
  • 5
    Since Asp.NET 4.7.2 you can do the same thing by adding the following line to the `` node in the Web.config. `` – L01NL May 28 '18 at 11:22
  • That's great v4.7.2 supports same site functionality, however that's a perfect world situation. Not everyone can upgrade an entire application(s) to the latest version of .NET without spending days, weeks or months making the leap to the latest version when dealing with enterprise size projects. – Damian May 29 '18 at 09:35
  • 7
    I tried with in .Net 4.7.2 but it did not work for the Asp.Net Identity cookie. This rewrite rule did. – Augusto Barreto Nov 22 '18 at 22:30
  • 1
    @AugustoBarreto Asp.Net Identity ignore the .config settings. Solution is to implement your own Cookie Handler. Derive from System.IdentityModel.Services.CookieHandler and implement WriteInternal method. – Saftpresse99 Mar 18 '19 at 12:18
  • lets say i have two urls, a.abc.com and b.abc.com, both pointing to same site. this rule works when i access a.abc.com, where was when i try b.abc.com, it is giving anti-forgery token error. any suggestions? – user1447718 May 06 '19 at 21:30
  • 3
    @L01NL I'm targeting 4.7.2 and still get `Unrecognized attribute 'samesite'` also not mentioned in MS docs – Alex from Jitbit Sep 08 '19 at 07:58
  • For reference, this is in the MS docs at https://learn.microsoft.com/en-us/dotnet/api/system.web.httpcookie.samesite – Brian Oct 25 '19 at 17:41
  • This added the samesite attribute but it did not remove a default value for the attribute. there was there for two values for samesite. I used instead and it removed the other value. – Joe Dec 20 '19 at 22:57
  • @Alex and for reference, the system.web config XML is case sensitive and camel cased, e.g. . I tried this in .NET Franework 4.8.03752 and it set the SameSite cookie attribute on all cookies *except* for the ASP.NET_SessionId cookie. – redcalx Jan 10 '20 at 10:44
  • This fix worked for me in all browsers apart from IE? anyone else seeing this? – Stephen Jan 23 '20 at 11:44
  • [These docs](https://learn.microsoft.com/en-us/aspnet/samesite/system-web-samesite) spell out which tags have which attributes -- some support `requireSSL`, some support `sameSite`, and some support both. – Coderer Jan 28 '20 at 14:01
  • this seems to be the easiest pre 4.7.2 solution – Sam Feb 05 '20 at 12:06
34

You can also set this in code when creating a cookie:

var httpCookie = new HttpCookie("mycookie", "myvalue");
httpCookie.Path += ";SameSite=Strict";

Response.SetCookie(httpCookie);

This will give you the following header:

Set-Cookie:mycookie=myvalue; path=/;SameSite=Strict

bit of a hack until it's pushed in to the framework.

Kevin Smith
  • 13,746
  • 4
  • 52
  • 77
  • better solution! but, on Response you can only read cookie but you CAN T modified it...you have to create a new one. – elle0087 Aug 26 '20 at 13:37
27

Just adding my answer to systematize all the info found here and in other places.

1. To secure custom cookies under 4.7.2 and later

var c = new HttpCookie("test");
c.SameSite = SameSiteMode.Lax;

2. To secure Forms authentication cookie

In web.config

<authentication mode="Forms">
    <forms ..... cookieSameSite="Lax" />
</authentication>

3. To secure ASP.NET Session cookie

In Global.asax

void Session_Start(Object sender, EventArgs e)
{
    Response.Cookies["ASP.NET_SessionId"].SameSite = SameSiteMode.Lax;
    //while we're at it lets also make it secure
    if (Request.IsSecureConnection)
        Response.Cookies["ASP.NET_SessionId"].Secure = true;
}

Fun fact: even if you set <httpCookies requireSSL="true" /> the ASP.NET session cookie will still be non-secure for some reason.

3(a). UPDATE 01.2020: .NET 4.8 Session cookie is now "SameSite" by default

Installing the latest Windows Update will make your session cookies Lax by default. You can control it here:

<sessionState cookieSameSite="Lax" /> <!-- in system.web -->

4. <httpCookies samesite=xxx> does not exist?

Adding <httpCookies sameSite="Strict" /> like suggested in the comment above in web.config didn't work, I was getting the error.

Unrecognized attribute 'samesite'

Even though I'm targeting 4.7.2. Tested on multiple project and multiple machines, also VS2019 does not show this in intellisense and MS docs do not mention it anywhere.

Alex from Jitbit
  • 53,710
  • 19
  • 160
  • 149
  • 1
    I'm working with a legacy .NET 4.5 application and having a hard time. It looks like [the Nov. 2019 security update](https://www.sevenforums.com/news/421611-net-framework-november-2019-preview-quality-rollup-windows-7-a.html) forced everything to be `SameSite=Lax` as you say, and while it says this behavior can be changed in `web.config`, it's only actually supported in 4.7.2 and above. I'm going to try `rewrite` from the accepted answer next. – Coderer Jan 28 '20 at 14:03
  • 3
    I am using 4.7.2 and getting warning under error list "The 'sameSite' attribute is not allowed.". It allows me to build the solution but not sure about this warning. – Ravi Khambhati Jan 30 '20 at 19:11
  • Currently most browsers are automatically increasing cookies to Lax if Same-Site is not specified, so in case someone wants the opposite (reduce the security back to None), I've made a similar solution [here](https://stackoverflow.com/a/60117727/3606250) (based on the answer above) – drizin Feb 07 '20 at 17:15
  • 2
    How to implement the solution within .NET 4.6.2? – NoName May 19 '20 at 03:50
  • Thanks for " does not exist". Why do people spread false informations like that? – edc65 Aug 18 '20 at 08:30
18

.NET 4.7.2 has now built-in support for SameSite property.
The HttpCookie has now a property called SameSite.
See more info here from Microsoft.

No need anymore to hack this through the config file.

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
tif
  • 1,109
  • 2
  • 12
  • 32
13

In order to have SameSite defined to ASP.NET_SessionId cookie I had to set the web.config under system.web section:

<sessionState cookieSameSite="Lax" />
Andre RB
  • 306
  • 4
  • 7
9

Because in this day and age we use owin to fix the same silly webapi cookie bug...

public class CookieSameSiteMiddleware : OwinMiddleware
{
    public CookieSameSiteMiddleware(OwinMiddleware next) : base(next)
    {
    }

    public override async Task Invoke(IOwinContext context)
    {
        var url = context.Request.Path.Value.ToLowerInvariant();

        if (url.Contains("/api/mylogin"))
        {
            context.Response.OnSendingHeaders(x =>
            {
                var scv = context.Response.Headers.FirstOrDefault(h => h.Key == "Set-Cookie");
                if (!scv.Equals(default(KeyValuePair<string, string[]>)))
                {
                    //context.Response.Headers.Remove("Set-Cookie");
                    context.Response.Headers.Set("Set-Cookie", scv.Value[0] + "; SameSite=strict");
                }

            }, null);
        }

        await this.Next.Invoke(context);
    }
}

Make sure the middle-ware is registered before .UseWebApi()

maxfridbe
  • 5,872
  • 10
  • 58
  • 80
  • 2
    +1 This approach worked well. There's a small bug in the code—it filters out cookies when your login page sets more than one cookie. I fixed the bug and polished up the code [here](https://gist.github.com/mkropat/e98bf09be76f7bea9cca91aa21b725de). – Michael Kropat Dec 18 '18 at 22:00
4

Pre 4.7.2 you can just append the string to the cookie path.

FormsAuthentication.SetAuthCookie(username, false, FormsAuthentication.FormsCookiePath + "; SameSite=Lax");
Jacob
  • 7,741
  • 4
  • 30
  • 24
0

https://www.nuget.org/packages/Microsoft.Owin.Security.Cookies/4.1.0 now supports SameSite.

That is very good news because the other solutions here doesn't work that brilliantly:

Implementing OwinMiddleware: Works great, except for performance. This might be something specific for our environment but that solution was about 10% of our CPU.

<outboundRules>: Probably possible to get working. But all solutions I've seen so far and we tested, including the one in this thread, had some issues when multiple cookies where set in the same response.

Mikael Eliasson
  • 5,157
  • 23
  • 27