In this tip, we will look into Cookie authentication events and how it allows subscribing to events raised during cookie authentication. We will see how to know the cookie and its values by subscribing to the cookie authentication events and what are the main parts of the cookie authentication events.
Introduction
Sometimes, we have to do logging on Cookies for debugging in development site or in the production site. We had a situation like that.
Background
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 happens automatically whenever the login required. Once, we had an issue that was requested from our client that passed authentication for one request but failed for the next request that was raised immediately after the first request to the same URI. We haven't encountered that situation in any other apps. That error happened in one or two devices only over 200 devices.
Then we started debugging the session. First, we verified whether the login token is valid or not, that is valid, then we move to the next step of our process. Whatever we did on the business side always looked fine from any perspective. We had no idea what was going on. If at all that problem existed in API side, why did select one or two devices have problem, not all?
Finally, we 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 the problem is in the API side. If the cookie is not what we have given to them, then the problem is on the app side. To do this debug session, we started analyzing how to log the cookie. To know/log the cookie, we have to know the following details:
- Cookie generated by the 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
- Middleware to know the submitted cookie
Cookie Authentication Events
Allows subscribing to events raised during cookie authentication. By subscribing to the cookie authentication events, we can know the cookie and its values. Mainly, this cookie authentication event has the following events:
RedirectToAccessDenied
RedirectToLogin
RedirectToLogout
RedirectToReturnURL
SigningIn
SignedIn
SignedOut
ValidatePrincipal
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)
{
return base.RedirectToAccessDenied(context);
}
public override Task SigningIn(CookieSigningInContext context)
{
return base.SigningIn(context);
}
public override Task SignedIn(CookieSignedInContext context)
{
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 are 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 CookieAuthenticationEvents
, we will make the following changes on the above code block:
public void ConfigureServices(IServiceCollection services)
{
...
services
.AddAuthentication()
.AddCookie("", options =>
{
...
options.Events =
new MyCookieAuthenticationEvents();
});
...
}
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);
)
}
}
To work this middleware, we have to add it to the ApplicationBuilder
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();
...
app.UseMvc();
}
This cookie logging middleware should be presented between UseAuthentication
and UseMvc
middleware definitions. Done! Now try logging cookie.
Precautions
Authentication cookies are more sensitive information. If anyone gets this information, then we will be in trouble, so please be aware of this. Do not enable it permanently and also do not log/write the cookie in any public place which is accessed by a third person.
Conclusion
This tip may help someone who looking for the solution to log cookies generated by server and sumitted by the client applications. Thank you for reading!
History
- 30th June, 2021: Initial version