Debugging cookie problems in ASP.NET Core

Debugging cookie problems in ASP.NET Core

Troubleshooting cookie problems in ASP.NET Core

Having answered over 1000 questions on Stack Overflow, I’ve found that cookie-related issues are a frequent challenge for developers using ASP.NET Core, especially when implementing authentication and OpenID Connect.

Cookie problems can, in my experience, be categorized into the following categories:

  • Browser Rejection
    Cookies provided by the server that aren’t accepted by the browser.
  • Browser Omission
    Cookies in the browser are not included in requests to the server.
  • Lost cookies
    Cookies that are lost on the way to the server.

In this post, we’ll explore common ASP.NET Core cookie problems—such as browser rejection, missing cookies in requests, and lost cookies. You’ll learn practical tips to identify, diagnose, and resolve these issues, ensuring smoother authentication flows and a more reliable application experience.

Cookies rejected by the browser

When setting a cookie, we use the set-cookie response header, often accompanied by the secure and samesite attributes. Below is an example illustrating the setting of five common cookies:

				
					HTTP/1.1 200 OK

Set-Cookie: NormalCookie=NormalValue;Path=/

Set-Cookie: NormalCookieWitSecure=NormalValueSecure;Path=/;secure

Set-Cookie: StrictCookie=StrictValue;Path=/;SameSite=Strict

Set-Cookie: LaxCookie=LaxValue;Path=/;SameSite=Lax

Set-Cookie: NoneCookie=NoneValue;Path=/;SameSite=None;Secure

…
				
			

(Note: This article will not discuss the details of the pathdomain, and the HttpOnly attribute. The HttpOnly attribute is all about restricting JavaScript from accessing cookies.). I recommend setting the HttpOnly attribute on every cookie that never needs to be accessed by JavaScript.

How can I tell if the browser accepts a cookie?

The first step in troubleshooting cookie problems is to verify that the browser has accepted the cookie.

To see which cookies it has received and accepted, open the browser developer tools (F12) in Chrome and look under Application -> Storage -> Cookies.

How to view the cookies for the current page.

If the expected cookies are not found here, then head over to the Network tab, locate the request that sets the cookie, and then click on the Cookies sub-tab:

How to view the cookies for a given request in the network tab.

 

Rejected cookies are highlighted in yellow. Hovering over the information (i) icon displays reasons for the blockage. As shown in the example below:

Example of rejected cookies in the browser

You can also activate the “Has blocked cookies” checkbox to only show requests with blocked response cookies.

Some of the most common reasons for blocking are:

  • Using samesite=none without the secure attribute
  • Trying to set a cookie with the secure attribute over HTTP://
  • Too large cookies; keep the cookie size below 4000 bytes for maximum browser compatibility. 

Cookies not included in requests

If you have concluded that the browser has accepted the cookie and it is found under Application -> Storage, great! One step forward! What’s next?

There are a few reasons why the browser might decide not to include cookies in outgoing requests:

Some of the reasons for blocking are:

  • Protocol Mismatch
    Cookies with the secure attribute will not be included in requests over HTTP.
  • Incorrect samesite
    For cross-site requests, you must use:

    • samesite=none;secure when you need to support GET & POST in requests to another site

    • samesite=lax when you only need to support GET requests across sites.

  • Cross-Origin Resource Sharing (CORS)
    We won’t go into CORS in this blog post. CORS can be problematic when you do API requests from JavaScript using the XMLHttpRequest or Fetch APIs.

Under the network tab, you can see why a cookie was not included in the request, as shown in the example below:

Example of how the browser blocks cookies due to the samesite attribute.

 

Common SameSite Cookie Problems

Some of the common samesite problems that I see are:

  • SameSite=none cookies
    Cookies set with the samesite=none attribute must also be marked with the secure attribute. This means that they must always be used over HTTPS, a common problem, for example, when working with OpenID Connect.
  • Missing samesite header?
    All cookies that you set should have a samesite attribute. Otherwise, you might end up with unexpected issues where browsers will start to block them in certain circumstances.

    For example, Firefox writes this warning to the console when you try to set a cookie without a valid samesite attribute:

Cookie “NormalCookie” does not have a proper “SameSite” attribute value. Soon, cookies without the “SameSite” attribute or with an invalid value will be treated as “Lax”. This means that the cookie will no longer be sent in third-party contexts. If your application depends on this cookie being available in such contexts, please add the “SameSite=None“ attribute to it. To know more about the “SameSite“ attribute, read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite 

Which samesite value should you use?

Some guidance about what value to use:

  • Strict
    Use this value for cookies that should only be used within the same site. For example, consider using this value for your session cookie. Using strict cookies provides the maximum protection against Cross-Site Requests.
  • Lax
    This is the new default for cookies, which only includes the cookie GET requests across sites.
  • None
    Use this value for cookies that should be included in all site requests. This value must be set together with the secure attribute. This is the least secure option. This makes the cookies behave like they behaved before the samesite concept was introduced. 

Cookies in ASP.NET Core

What can go wrong when we use cookies in ASP.NET Core?

When you use the cookie authentication handler, the default session cookie is set as follows:

				
					Set-Cookie: .AspNetCore.Cookies=xxxxxxx; path=/; secure; samesite=lax; httponly
				
			

This is a sensible default. You might be tempted to set the session cookie to samesite=strict, as follows:

				
					
builder.Services.AddAuthentication()

                .AddCookie(opt =>

                {

                   opt.Cookie.SameSite = SameSiteMode.Strict;

                });
				
			

If you just use local authentication (like ASP.NET Core Identity), that is usually fine. But, when you use it together with OpenID Connect, you will have problems, as shown in the image below:

OpenID Connect Cookies blocked by the browser

OpenID Connect, cookies, and IdentityServer

When you work with OpenID Connect, plenty of cookies will be involved. For example, if you use Duende IdentityServer, then the following cookies are involved during authentication:

Overview of the cookies used when authenticating using OpenID Connect

Not properly configuring and understanding these cookies is a common source of problems.

Same domain but different ports

You might think that when you have multiple sites on the same domain but on different ports, they would have separate cookie jars:

But it turns out that they will all share the same cookie jar. The cookies are tied to the domain, not the port or scheme.

Summary

I hope the steps outlined above can help you troubleshoot your cookie problems. Here are some tips for healthier and more secure cookies:

  • Always use HTTPS
    Most cookie problems will go away when you move your traffic to HTTPS. Using HTTPS today is also a must If you care about security.
  • Set samesite
    Always add the correct samesite attribute; this is a must today.
  • Add the secure and HttpOny attribute
    Securing our cookies and all sensitive cookies should always have these two attributes set.
  • Do research the path and domain attributes
    They can be used to further restrict to what domain (including sub-domains) and path the cookies should be included on.

Feedback, comments, found any bugs?

Let me know if you have any feedback, anything I missed, or any bugs/typos. You can find my contact details here.

About the author

Hi, I’m Tore! I have been fascinated by computers since I unpacked my first Commodore VIC-20. Today, I enjoy providing freelance development and developer training services, focusing on ASP.NET Core, IdentityServer, OpenID Connect, Architecture, and Web Security. You can connect with me on LinkedIn and Twitter, and you can find out more about me and my services here, as well as my courses for developers, including my course, Introduction to IdentityServer and OpenID-Connect.

Share This Story

Related Posts

About me

My name is Tore Nestenius and I’m a trainer and senior software developer focusing on Architecture, Security and Identity, .NET, C#, Backend, and Cloud, among other things.

Do You Want Tore To Be Your Mentor?

Categories