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 discussions of adding roles to claims within the community.
My requirements are simple:
I've spent countless hours trying different configurations to get asp.net Identity roles to be passed to my MVC application after authentication but without luck. The purpose is as described in point 6.
I've also spent countless hours reading but I have a feeling that the implementation IdentityServer4.AspIdentity regarding roles has changed a lot since the version v1.0.0.
After reading a lot about this, it remains unclear how to actually implement this as it seems that some of the solution described only 2 months ago are no longer valid.
So, for now I believe there are 2 paths:
Anyway, that's my assumptions.
So, please help out and explain/document in detail so we can start implementing this in a durable way? Some workable examples would be great as well.
Roles can be created in AdminUI in order to create the roles you need within your application. By clicking "Add Role", we can create a new role within the AdminUI application.
When using reference tokens - IdentityServer will store the contents of the token in a data store and will only issue a unique identifier for this token back to the client. The API receiving this reference must then open a back-channel communication to IdentityServer to validate the token.
The current version (IdentityServer4 v4. x) will be the last version we work on as free open source. We will keep supporting IdentityServer4 until the end of life of . NET Core 3.1 in November 2022.
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?}");
});
}
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