IdentityServer4:[Authorize(Roles = "Admin")] 即使 JWT 令牌具有 {"role": "Admin"} 声明也不授予管理员用户访问权限

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

我的问题是,即使登录用户是管理员,他仍然无法访问具有 [Authorize(Roles = "Admin")] 属性的控制器。

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

身份服务器 4

我已经设置了我的身份服务器 4,并且与 OpenId 连接配合得很好。没问题。

客户项目

有一个客户端项目只有一个 Web api,它由 [Authorize(Roles = "Admin")] 属性保护。

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

是URL是https://localhost:5002/WeatherForecast

现在:我在浏览器中打开这个安全 URL,我被重定向到 IdnentityServer 登录页面,我在其中输入管理员用户的用户名和密码。

之后发生的事情是我被重定向到 https://localhost:5002/Account/AccessDenied?ReturnUrl=%2FWeatherForecast 页面(这不应该是因为用户具有管理员角色)。

在控制台上我收到错误 -

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

在 jwt 网站上解码令牌时,我可以清楚地看到 "role": "Admin" 那里。见下图:

所以我可以说我的令牌上有管理员角色声明,因此它应该能够访问安全控制器。 但是没有发生??

如果我从属性属性中删除角色 - [Authorize] 那么我就可以使用令牌访问控制器。见下图:

代码:

startup.cs ConfigureServices 方法是我添加 Openid 连接代码的地方:

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;
});

我不分享 IdentityServer 的代码,因为令牌正在生成 属性,我认为 IdentityServer 没有任何问题。

那么这里可能是什么问题,为什么基于角色的 IdentityServer 4 身份验证在我的案例中失败?

由于某种原因会出现此问题。请检查以下步骤。

1.The问题可以按AuthenticationAuthorization的顺序在管道中,确保Authentication放在Authorization之前。

2.You 必须在 Startup.cs 中添加以下代码行以启用 RoleManager。

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

3.According到这个GitHub Link,把这行代码加到ConfigureServices

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

请检查所有步骤。我认为这将有助于解决您的问题。

如果它在邮递员上工作,我认为您的 openid 连接配置有问题。检查身份服务器 openid 连接 documentation

您必须将角色声明类型引入您的应用程序。在 .AddJwtBearer 选项中,有一个地方可以在令牌验证参数中设置角色声明类型:

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

然后在 IDS4 的配置文件中,为您的应用添加 Jwt 声明类型“Role”:

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
            }
        },