We would like to add a lot of role claims to the current principal (we use the Authorize(Roles)
attribute), and found the IClaimsTransformer
that looks like a perfect fit.
We've registerd it like this
app.UseClaimsTransformation(new ClaimsTransformationOptions
{
Transformer = new GetRolesFromDatabaseClaimsTransformer(new RoleManager2(Configuration.GetConnectionString("ourcoolapp")))
});
And the transform is like this:
public Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
{
// A hacky way to not load on all requests. Better ideas?
if (!context.Context.Request.Path.Value.Contains("api/"))
{
return Task.FromResult(context.Principal);
}
var roleClaims = RoleManager.GetRolesForUser(context.Principal.Identity.Name).Select(roleName => new Claim("role", roleName));
var claims = new List<Claim> { };
var identity = context.Principal.Identity as ClaimsIdentity;
claims.AddRange(identity.Claims);
claims.AddRange(roleClaims);
var userIdentity = new ClaimsIdentity(claims, "local");
var userPrinicpal = new ClaimsPrincipal(userIdentity);
return Task.FromResult(userPrinicpal);
}
Question: Are there alternative, or smarter ways of adding the role claims?
Thanks
Larsi
Another option could be UserClaimsPrincipalFactory
It provides methods to create claims principal for a given user and you can customize it just like ClaimsTransformer
.
By default It adds UserName
and UserId
to claim collection.
In order to customize it you can driver from UserClaimsPrincipalFactory
and override CreateAsync
public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<User, Role>
{
public AppClaimsPrincipalFactory(UserManager<User> userManager,
RoleManager<Role> roleManager,
IOptions<IdentityOptions> optionsAccessor,
ILogger<AppClaimsPrincipalFactory> logger)
: base(userManager, roleManager, optionsAccessor)
{
logger.LogInformation("AppClaimsPrincipalFactory ctor");
}
public override async Task<ClaimsPrincipal> CreateAsync(User user)
{
var principal = await base.CreateAsync(user);
((ClaimsIdentity)principal.Identity).AddClaims(new []
{
new Claim("Foo", "Bar"),
});
return principal;
}
}
And Register the Factory in DI:
services.AddScoped<IUserClaimsPrincipalFactory<User>, AppClaimsPrincipalFactory>();
It will change/override the claim whenever the user's claims requested.
For more info take a look at source at GitHub.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With