There's already a class that can provide claims enrichment ClaimsAuthenticationManager, which you can extend so it handles your domain-specific claims, for example...
public class MyClaimsAuthenticationManager : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return base.Authenticate(resourceName, incomingPrincipal);
}
return AddApplicationClaims(incomingPrincipal);
}
private ClaimsPrincipal AddApplicationClaims(ClaimsPrincipal principal)
{
// TODO: Add custom claims here based on current principal.
return principal;
}
}
Next task is to provide appropriate middleware to invoke this. For my projects I've written the following classes...
/// <summary>
/// Middleware component to apply claims transformation to current context
/// </summary>
public class ClaimsTransformationMiddleware
{
private readonly Func<IDictionary<string, object>, Task> next;
private readonly IServiceProvider serviceProvider;
public ClaimsTransformationMiddleware(Func<IDictionary<string, object>, Task> next, IServiceProvider serviceProvider)
{
this.next = next;
this.serviceProvider = serviceProvider;
}
public async Task Invoke(IDictionary<string, object> env)
{
// Use Katana's OWIN abstractions
var context = new OwinContext(env);
if (context.Authentication != null && context.Authentication.User != null)
{
var manager = serviceProvider.GetService<ClaimsAuthenticationManager>();
context.Authentication.User = manager.Authenticate(context.Request.Uri.AbsoluteUri, context.Authentication.User);
}
await next(env);
}
}
And then a wiring extension...
public static class AppBuilderExtensions
{
/// <summary>
/// Add claims transformation using <see cref="ClaimsTransformationMiddleware" /> any depdendency resolution is done via IoC
/// </summary>
/// <param name="app"></param>
/// <param name="serviceProvider"></param>
/// <returns></returns>
public static IAppBuilder UseClaimsTransformation(this IAppBuilder app, IServiceProvider serviceProvider)
{
app.Use<ClaimsTransformationMiddleware>(serviceProvider);
return app;
}
}
I know this is service locator anti-pattern but using IServiceProvider is container neutral and seems to be the accepted way of putting dependencies into Owin middleware.
Last you need to wire this up in your Startup, example below presumes Unity and registering/exposing a IServiceLocator property...
// Owin config
app.UseClaimsTransformation(UnityConfig.ServiceLocator);