I have a controller that I want to restrict only to a specific role, let\'s say admin
. After setting a user with the admin
role, I can validate tha
I think that what you need is to check claims, not roles. Add an AuthorizeAttribute
such as:
[Authorize(Policy = "AdminOnly")]
And then configure a policy that requires a claim:
services.AddAuthorization(options =>
{
options.AddPolicy("AdminOnly", policy =>
policy.RequireClaim(OpenIdConnectConstants.Claims.Role, "Admin"));
});
Or, for debugging purposes or more advanced validation, you could have:
services.AddAuthorization(options =>
{
options.AddPolicy("AdminOnly", policy =>
policy.RequireAssertion(ctx =>
{
//do your checks
return true;
}));
});
You likely get a 404 response because Identity - which is automatically configured as the default authentication, sign-in/sign-out and challenge/forbidden scheme by services.AddIdentity()
- tries to redirect you to the "access denied page" (Account/AccessDenied
by default), that probably doesn't exist in your application.
Try to override the default challenge/forbidden scheme to see if it fixes your issue:
services.AddAuthentication(options =>
{
// ...
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
});
To fix your second issue, make sure the JWT claims mapping feature is disabled. If it's not, the JWT handler will "convert" all your role
claims to ClaimTypes.Role
, which won't work as you configured it to use role
as the role claim used by ClaimsPrincipal.IsInRole(...)
(RoleClaimType = OpenIdConnectConstants.Claims.Role
).
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
// ...
options.SecurityTokenValidators.Clear();
options.SecurityTokenValidators.Add(new JwtSecurityTokenHandler
{
// Disable the built-in JWT claims mapping feature.
InboundClaimTypeMap = new Dictionary<string, string>()
});
});