IdentityServer4: [Authorize(Roles = "Admin")] not granting access to Admin User even when the JWT Token has {"role": "Admin"} claim

Viewed 817

My problem is that even when the logged on user is an Admin still he is not able to access the Controller with [Authorize(Roles = "Admin")] attribute.

Note: The codes works perfectly fine on postman testing but not on openid connect.

IdentityServer 4

I have my Identity server 4 set up and working great with OpenId connect. No problem with it.

Client Project

There is a client probject just having a web api which is secured with [Authorize(Roles = "Admin")] attribute.

[ApiController]
[Route("[controller]")]
[Authorize(Roles = "Admin")]
public class WeatherForecastController : ControllerBase
{
......
}

It's URL is https://localhost:5002/WeatherForecast.

Now: I open this secured URL in the browser, I am redirected to the IdnentityServer login page where I enter the username and password of admin user.

After that what happens is that I am redirected to https://localhost:5002/Account/AccessDenied?ReturnUrl=%2FWeatherForecast page (which should not be as user has admin role).

enter image description here

On the console I get the error -

Authorization failed. These requirements were not met: RolesAuthorizationRequirement:User.IsInRole must be true for one of the following roles: (Admin)

enter image description here

On decoding the token on jwt site, I can clearly see "role": "Admin"there. See the below image:

enter image description here

So I can say My token has Admin role claim on it and it should therefore be able to access the secured controller. But it does not happen??

If i remove the roles from attribute attribute - [Authorize] then I am able to access the controller with the token. See image below:

enter image description here

The Codes:

The startup.cs ConfigureServices method is the place where I have added the Openid connect codes:

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddJwtBearer(options =>
{
    options.Authority = "https://localhost:5001";
    options.Audience = "IS4API";
})
.AddOpenIdConnect("oidc", options =>
{
    options.Authority = "https://localhost:5001";
    options.ClientId = "postman";
    options.ResponseType = "code";
    options.Scope.Add("fullaccess");
    options.SaveTokens = true;
});

I am not sharing the codes for IdentityServer because the token is generating property and I don't think there is any problem on IdentityServer.

So what can be the problem here, why roles based IdentityServer 4 authentication failing on my case?

3 Answers

If it's working on postman, in my opinion something wrong in your openid connect configuration. Check the identity server openid connection documentation

You have to bring the role claim types into your app. Inside .AddJwtBearer options there's a place to set the role claim type inside the token validation paramters:

options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = false,
                    NameClaimType = "name",
                    RoleClaimType = "role"
                };

Then inside the config file in IDS4, add the Jwt claim type "Role" for your app:

new ApiScope
        {
            Name = "myAPI",
            DisplayName = "my API",
            Enabled = true,
            UserClaims =
            {   JwtClaimTypes.Name,
                JwtClaimTypes.Email,
                JwtClaimTypes.Subject,
                JwtClaimTypes.Role,
                JwtClaimTypes.Address,
                JwtClaimTypes.Confirmation,
                JwtClaimTypes.EmailVerified,
                JwtClaimTypes.Id,
                JwtClaimTypes.Profile
            }
        },

This problem will happen for some reason. please check the below steps.

1.The problem can be in the order of Authentication and Authorization in the pipeline, make sure Authentication is placed before Authorization.

2.You must add the following line of code in Startup.cs to enable RoleManager.

services.AddDefaultIdentity<ApplicationUser>()
   .AddRoles<IdentityRole>() // <-- Add this line
    .AddEntityFrameworkStores<ApplicationDbContext>();

3.According to this GitHub Link, Add this line of code to ConfigureServices

// Add Role claims to the User object
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>>();

Please check all steps. I think it will help resolve your issue.

Related