Beware in ASP.NET Core 2.0: Claims transformation might run multiple times
August 30, 2017
In ASP.NET Core, you can add a claims transformation service to your application, as such:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddAuthentication(options=> { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }).AddCookie(); services.AddTransient<IClaimsTransformation, ClaimsTransformer>(); }
And then your ClaimsTransformer might look like this:
class ClaimsTransformer : IClaimsTransformation { public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) { ((ClaimsIdentity)principal.Identity).AddClaim(new Claim("now", DateTime.Now.ToString())); return Task.FromResult(principal); } }
And that might be fine. But beware that this might be invoked multiple times. If an app has this code (perhaps in different locations in the app which might be likely):
await HttpContext.AuthenticateAsync(); await HttpContext.AuthenticateAsync();
Then each time AuthenticateAsync is called the claims transformer is invoked. So given the above implementation we’d be adding the “now” claim multiple times.
Moral of the story, claims transformation should be more defensive and/or return a new principal, as such:
class ClaimsTransformer : IClaimsTransformation { public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) { var id = ((ClaimsIdentity)principal.Identity); var ci = new ClaimsIdentity(id.Claims, id.AuthenticationType, id.NameClaimType, id.RoleClaimType); ci.AddClaim(new Claim("now", DateTime.Now.ToString())); var cp = new ClaimsPrincipal(ci); return Task.FromResult(cp); } }
HTH
9 Comments
leave one →
Are you sure this is .net core 2.0 code?
services.AddAuthentication(options=>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie();
It doesn’t work. What works is :
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IISDefaults.AuthenticationScheme;
});
And I cant seem to find where AddCookie() is and what it’s use is.
Yea, but it might have been against a RC/pre-release.
how can we invoke TransformAsync in startup class
IIRC, they changed it so you must inject it as a service now in 2.0.
How to use it in windows authentication scenario
Claims transformation should works with windows auth, as it’s an unrelated feature.
IClaimsTransformation not triggerd in asp.net core 2.2 if inprocess is configured
https://github.com/aspnet/AspNetCore/issues/6962
yea, that’s because their windows authN isn’t quite following the same model as the rest of the authentication services and handlers in ASP.NET Core
It still adds the new claim multiple times in .net core 2.1