Thanks to the answers in this thread, I was able to get this working for myself too. What isn't addressed here is that if claims need to be modified which requires a service. In my case, I needed to build the service provider in order to get the proper dependencies in order to transform the claims. (I also was able to delete claims without a transformation - showing that code here as well).
public void ConfigureServices(IServiceCollection services)
{
services
.AddAuthentication(options =>
{
// set options
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
// set options
})
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
// options such as Authority, ClientId, etc set here
options.Authority = "your-value";
options.ClientId = "your-value";
// ...
// remove automatically mapped claims we do not need, keeps the authentication cookie smaller
options.ClaimActions.DeleteClaim("sid");
options.ClaimActions.DeleteClaim("idp");
options.ClaimActions.DeleteClaim("s_hash");
options.ClaimActions.DeleteClaim("auth_time");
options.Events.OnTicketReceived = async context =>
{
// Build the service provider and necessary dependencies
// in order to enhance our claims once we receive it initially
ServiceProvider serviceProvider = services.BuildServiceProvider();
ICustomProvider customProvider = serviceProvider.GetService<ICustomProvider>();
EnhanceClaimsTransformation claimsTransformation = new EnhanceClaimsTransformation(customProvider);
context.Principal = await claimsTransformation.TransformAsync(context.Principal);
await Task.CompletedTask;
};
});
}
EnhanceClaimsTransformation
(ICustomProvider is registered in dependency injection in ConfigureServices
)
Do note that in this code we need to make a clone of the principal to actually add claims to it.
public class EnhanceClaimsTransformation : IClaimsTransformation
{
private readonly ICustomProvider _customProvider;
public EnhanceClaimsTransformation(ICustomProvider customProvider)
{
_customProvider = customProvider;
}
/// <summary>
/// Upon authentication, we transform the claims in order to enhance
/// the claims with user-enhanced values.
/// </summary>
/// <param name="principal"></param>
/// <returns></returns>
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
// https://gunnarpeipman.com/aspnet-core-adding-claims-to-existing-identity/
ClaimsPrincipal clone = principal.Clone();
ClaimsIdentity claimsIdentity = (ClaimsIdentity)clone.Identity;
Response response = await _customProvider.Find(principal.Identity.Name, CancellationToken.None);
// Setting claims values
claimsIdentity.AddClaims(new List<Claim>
{
new Claim("Datapoint1", response.Datapoint1),
new Claim("Datapoint2", response.Datapoint2),
// ...
});
return clone;
}
}