Although I am very happy that IdentityServer4 exists and makes life I with regards to authentication much easier in many ways, I\'ve stumbled onto the problem and the many discu
So, after investigation I’ve come up with 2 methods to do this:
Include on Identity Server Side
ravi punjwani provided the answer in ‘How to add additional claims to be included in the access_token using ASP.Net Identity with IdentityServer4. His solution is still in draft but the solution allows you to add any claim before the token is send back to the client. This is the link: How to add additional claims to be included in the access_token using ASP.Net Identity with IdentityServer4
Include on Client side
This one is a little tougher as it involves adding ‘IClaimsTransformer’ in the request pipeline of the client. The result is that per request, the Claimstransformer will retrieve the claims for the user and add it to the User Identity claims (the token). The set-up of the Claimstransformer is not easy as it’s tricky to get DI to work but after lots of research the celow solution does it for me.
The Custom ClaimsTransformer class does the transformation in the Middleware: public class KarekeClaimsTransformer : IClaimsTransformer { private readonly UserManager _userManager;
public KarekeClaimsTransformer(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
{
if (context.Principal.Identity.IsAuthenticated)
{
Claim userId = context.Principal.FindFirst("sub");
if (context.Principal.FindFirst("role") == null && userId != null)
{
ApplicationUser user = await _userManager.FindByIdAsync(userId.Value);
var roles = await _userManager.GetRolesAsync(user);
foreach (var role in roles)
{
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(JwtClaimTypes.Role, role,
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role"));
}
}
}
return Task.FromResult(context.Principal).Result;
}
}
In the Client start-up class you need to Add it to the scope in ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
...
services.AddScoped<IClaimsTransformer, KarekeClaimsTransformer>();
// Add framework services.
services.AddMvc();
}
Lastly, add in Configure:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ApiName = "api1"
});
app.UseClaimsTransformation((context) =>
{
IClaimsTransformer transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
return transformer.TransformAsync(context);
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "api/{controller}/{action?}/{id?}");
});
}