How To Correctly Delete Your SameSite Cookies In Chrome (80+)

In my last article I explained how the changes in Chrome 80 (February 2020) can break your existing web sites or web applications, because SameSite cookies will be treated differently. In that post I focused on how to correctly set your cookies and how to mitigate incompatibilities between different browsers, as certain Safari versions don't work correctly with the new way that Chrome enforces.

In diesem Artikel:

How To Correctly Delete Your SameSite Cookies In Chrome (80+)
Sebastian Gingter ist Consultant und „Erklärbär“ bei Thinktecture. Seine Spezialgebiete sind Backend-Systeme mit .NET Core und IdentityServer.

Update: If you want all details about what SameSite Cookies actually are and how they really work, I added a detailed post about that, too.

There is, however, an additional problem you can encounter.

Why doesn't Chrome delete my SameSite=None cookies?

In the new specification Google defines that in order to set a Cookie with SameSite=None, you also have to set the Secure flag.

While the current specification for cookies only describes that in order to delete a cookie, you set a new cookie with an expiry date in the past, it does specifically not require the new cookie (that will overwrite the old one) to set all flags like the original cookie.

With the changes that will be shipped in Chrome 80, this will alter this behavior, too: In order to delete a SameSite=None cookie, the replacement cookie with the expiry date in the past also needs to have the Secure flag set. If that is not the case, the cookie won’t be deleted (as in: the replacement cookie won’t be accepted by Chrome).

However, besides that the cookie should be deleted correctly, anyways. So the way to go is to pass CookieOptions that have set Secure to true when deleting the cookie like so:

				
					Response.Cookies.Delete("CookieName", new CookieOptions()
{
   Secure = true,
});
				
			

This will fix the deletion issue for that cookie. But again….

But my session stays active: The session cookie still isn't deleted!

Yes. There is another issue with that: The ASP.NET Core Authentication cookie is handled a bit differently and is managed by a CookieManager. Unfortunately, since the old spec did not require the secure flag, the code of the CookieManager in the .NET Core Framework (and also in .NET Full Framework) simply does not copy it over to the actual Cookies.Delete() call. Bummer.

If you don’t persist and manage your session on the server, and then rely on actually deleting the session cookie, it will simply stay there and your users will stay signed in into your website / application although they explicitly wanted to sign out.

Note: I strongly encourage you to handle your sessions on the server, so even when a session cookie accidentally stays there, the user will still be treated as signed out.

Luckily this issue should be fixed by Microsoft in .NET Core 3.x and .NET Core 2.1 in January 2020.

As this fix will likely ship in January 2020 and by then .NET Core 2.2 will already be beyond its support lifetime, Microsoft decided to not back-port that fix to .NET Core 2.2. And yes, while 2.2 actually is newer than 2.1, the 2.1 version is the one defined as long-term support (LTS) and as such only this version will get these fixes back-ported. In other words, if you are still on 2.2, you probably should update to .NET Core 3 😉.

If you are on .NET Core 2.2 and cant’t yet update to a version that will be supported for longer, or you are on 3.x or 2.1 and need that fix right now, just stay with me.

Correctly delete SameSite=None cookies in unfixed .NET Core versions

First of all, we need to back port the fix into our project. To do that, you grab the already patched ChunkingCookieManager from the ASP.NET Core repository and copy that class into your project.

Then we need to tell ASP.NET Core to use our patched CookieManager instead of the one that does not copy the Secure flag over.

To do this, we need to adjust our application startup. Locate where your authentication options are configured in your ConfigureServices method or nested calls therein.

				
					public void ConfigureServices(IServiceCollection services)
{
   // find this or similar
   services
      .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
      .AddCookie();
}
				
			

After you figured out where your cookie authentication is configured, adjust the code so that its going to use the patched ChunkingCookieManager instead of the default one:

				
					public void ConfigureServices(IServiceCollection services)
{
   // Adjust to this (or similar)
   services
      .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
      .AddCookie(options =>
      {
         // add an instance of the patched manager to the options:
         options.CookieManager = new ChunkingCookieManager();
      });
}
				
			

Voilà: This will copy the secure flag also over to the delete cookie call, and the new Chrome will be persuaded to really delete your session cookie. In the last weeks we successfully implemented that in several IdentityServer projects and could make sure the cookies were really deleted.

Also make sure that your SameSite cookies are correctly set, as explained in my other post about that.

Summary

Chrome will soon (February 2020) change its default behavior of handling cookies. In the future it will require the Secure flag to be set for SameSite=None cookies. This also applies to deleting these cookies.

While setting Secure = true on the CookieOptions is enough for normal cookies, this does not apply to ASP.NET Core Authentication cookies. There is a bug that prevents the secure flag to be copied to the actual cookie deletion call.

This bug should be fixed in January 2020, but only for .NET Core 2.1 LTS and .NET Core 3.x. For .NET Core 2.2 which is out of support or until the fix is released, this article provides a workaround that ensures that the secure flag will be copied and the cookie will still be deleted when Chrome 80 ships.

Kostenloser
Newsletter

Aktuelle Artikel, Screencasts, Webinare und Interviews unserer Experten für Sie

Verpassen Sie keine Inhalte zu Angular, .NET Core, Blazor, Azure und Kubernetes und melden Sie sich zu unserem kostenlosen monatlichen Dev-Newsletter an.

Diese Artikel könnten Sie interessieren
.NET
Incremental Roslyn Source Generators in .NET 6: Adapt Code Generation Based on Project Dependencies – Part 5

Incremental Roslyn Source Generators in .NET 6: Adapt Code Generation Based on Project Dependencies – Part 5

The Roslyn Source Generator, implemented in the previous articles of the series, emits some C# code without looking at the dependencies of the current .NET (Core) project. In this article our DemoSourceGenerator should implement a JsonConverter, but only if the corresponding library (e.g. Newtonsoft.Json) is referenced by the project.
08.07.2022
Unterschiede
.NET
Blazor WebAssembly vs. Blazor Server – Welche Unterschiede gibt es und wann wähle ich was?

Blazor WebAssembly vs. Blazor Server – Welche Unterschiede gibt es und wann wähle ich was?

Das Blazor Framework von Microsoft gibt es inzwischen in drei "Geschmacksrichtungen". Die erste ist Blazor WebAssembly, die zweite Blazor Server, und zu guter Letzt gibt es noch Blazor Hybrid. In diesem Artikel wollen wir uns die zwei "echten", also Browser-basierten, Web-Anwendungs-Szenarien WebAssembly und Server anschauen.
04.07.2022
Three different textured walls
.NET
Dependency Injection Scopes in Blazor

Dependency Injection Scopes in Blazor

The dependency injection system is a big part of how modern ASP.NET Core works internally: It provides a flexible solution for developers to structure their projects, decouple their dependencies, and control the lifetimes of the components within an application. In Blazor - a new part of ASP.NET Core - however, the DI system feels a bit odd, and things seem to work a bit differently than expected. This article will explain why this is not only a feeling but indeed the case in the first place and how to handle the differences in order to not run into problems later on.
31.05.2022
.NET
Asynchrone Operationen: Blazor WebAssembly für Angular-Entwickler – Teil 5 [Screencast]

Asynchrone Operationen: Blazor WebAssembly für Angular-Entwickler – Teil 5 [Screencast]

Eine Webanwendung will natürlich auch mit Daten gefüttert werden. Doch diese müssen irgendwo her kommen. Nichts liegt näher als diese von einer Web API zu laden. Dieser Screencast zeigt, wie asynchrone Operationen in Blazor funktionieren und welche gravierenden Unterschiede es zu Angular gibt.
26.05.2022
.NET
Typings: Blazor WebAssembly für Angular-Entwickler – Teil 4 [Screencast]

Typings: Blazor WebAssembly für Angular-Entwickler – Teil 4 [Screencast]

C# und TypeScript entstammen der Feder der selben Person. Doch sind sie deshalb auch gleich? In diesem Teil der Screencast-Serie erfahren Sie, wie mit Typen in den beiden Programmiersprachen verfahren wird und welche Unterschiede es gibt.
19.05.2022
.NET
Bindings: Blazor WebAssembly für Angular-Entwickler – Teil 3 [Screencast]

Bindings: Blazor WebAssembly für Angular-Entwickler – Teil 3 [Screencast]

Wer Komponenten einsetzt, steht früher oder später vor der Fragestellung, wie man Daten an die Komponente übergibt oder auf Ereignisse einer Komponente reagiert. In diesem Screencast wird gezeigt wie Bindings bei Komponenten funktionieren, also wie eine Komponente Daten von außerhalb benutzen und Rückmeldung bei Aktionen geben kann.
12.05.2022