Cookie logging in ASP Net Core
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.
Cookie Authentication Events
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.
Cookie Logging Middleware
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.