Cookie logging in ASP Net Core

4 minute read

Sometime we have to do logging on Cookies for debugging in development site or in the production site. We had a situation like that,

In our big Web API that serves data to the android client. We used authentication for that client and server communication. authentication of app is based on uniquely generated Authentication token. It is happened automatically whenever the login required. One time we had an issue that is request from out client passes authentication for one request but failed for next request which is raised immediately after the first request to the same URI. We haven’t met that situation in any other apps. that error happened in one or two devices only.

Then we have started debugging the session, First we have verified that the login token is valid or not, that is valid, then we are moved to next step of our process. Whatever we did in business side is always looking fine from any perspective. We had no idea what is going on. If at all that problem is exists in API side, why selected one or two devices having problem not all.

Finally, we have landed on the debugging session of what we are getting as cookie. because authentication is based on cookie only right. If that submitted cookie is valid then problem is in the API side. If the cookie is not what we have given to them then the problem is in app side. To do this debug session we have started analyzing how to log the cookie, To know/log the cookie we have to know following details

  • Cookie Generated by Server on login
  • Cookie Submitted By the Client on Each Request

For, this big question ASP.Net Core provides best solutions. We took

  • Cookie Authentication Events to Know the generated cookie
  • Middle ware to know the submitted cookie.

Allows subscribing to events raised during cookie authentication. By subscribing the cookie authentication events we can know the cookie and its values. Mainly this cookie authentication events has following events.

  • Redirect To Access Denied
  • Redirect To Login
  • Redirect To Logout
  • Redirect To Return URL
  • Signing In
  • Signed In
  • Signed Out
  • Validate Principal

we have used RedirectToAccessDenied, SignedIn,SigningIn events.

Finally Our CookieAuthenticationEvents class looks like this

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Threading.Tasks;

namespace Web
{
    public class MyCookieAuthenticationEvents : CookieAuthenticationEvents
    {
        public override Task RedirectToAccessDenied(RedirectContext<CookieAuthenticationOptions> context)
        {
		   //Logging The Required Details
            //Request Body has the client submitted cookie, if submitted 
            // Request available in the context. `context.HttpContext.Request`
         	return base.RedirectToAccessDenied(context);
        }

        public override Task SigningIn(CookieSigningInContext context)
        {
            //Logging The Required Details
            return base.SigningIn(context);
        }

        public override Task SignedIn(CookieSignedInContext context)
        {            
            //Logging The Required Details
           	//Generated new cookie informations available here. In the request Body. 
            // Request available in the HttpContext. `context.HttpContext.Request`
            return base.SigningIn(context);
        }
	}
}

We have to mention this is the cookie authentication event listener somewhere right, This is done in the place where we define cookie authentication schemes. In Our approach that is startup.cs class. This authentication configurations is done under the ConfigureServices section of startup.cs class. Somewhere in the startup class we definitely used something like below,

public void ConfigureServices(IServiceCollection services)
{
    ...
    
    services
        .AddAuthentication()
        .AddCookie("<Name Of the Authentication Scheme>", options => 
            { 
            	... 
        	});
    ...
}

To mention the Cookie authentication Events. we will do the following changes on the above code block

public void ConfigureServices(IServiceCollection services)
{
    ...
    
    services
        .AddAuthentication()
        .AddCookie("", options => 
            { 
            	...
                options.Events = new MyCookieAuthenticationEvents(); // this is newly added line
        	});
    ...
}

Now, This will tell us what cookie is generated and related details.

The second big portion of our analysis is logging the cookie. To do this we have decided to use middleware. Our cookie logging middleware looks like

using System.Threading.Tasks;

namespace Web
{   
    public class MyCookieLogMiddleware
    {
        private readonly RequestDelegate _next;

        public MyCookieLogMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            await _next.Invoke(context);
            
            //Logging the required details
            //Submitted Cookies available in the request. `context.Request.Cookies`
            //Generated or response cookies available in the response header. `context.Response.Headers["Set-Cookie"]`
        )                    
	}
}

To work this middleware we have to add it to the Application Builder of our application. Which is also possible via the startup.cs class. This Startup.cs class has the Configure method. this can done easily by having middleware extension.

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseMyCookieLogMiddleware(this IApplicationBuilder instance)
    {
        return instance.UseMiddleware<MyCookieLogMiddleware>();
    }
}

Finally In startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    ...
	app.UseAuthentication();
	app.UseCookieLogMiddleware(); //this is the line we have to include.
    ...
    app.UseMvc();
}

This cookie logging middleware should be presented between UseAuthentication and UseMvc middleware definitions.

Done! Now try logging cookie.