通过 AddIdentityServer 向 IdentityServer 设置添加声明

Car*_*pon 6 jwt openid-connect asp.net-core identityserver4

我有一个 SPA,它有一个 ASP.NET Core Web API 以及内置身份服务器AddIdentityServer,然后使用AddIdentityServerJwt

services.AddIdentityServer()
   .AddApiAuthorization<User, UserDataContext>();
services.AddAuthentication()
   .AddIdentityServerJwt();
Run Code Online (Sandbox Code Playgroud)

我还有一个需要“管理员”角色声明的授权策略设置:

services.AddAuthorization(options =>
{
    options.AddPolicy("IsAdmin", policy => policy.RequireClaim(ClaimTypes.Role, "Admin")); 
});
Run Code Online (Sandbox Code Playgroud)

我有一个使用此策略的控制器操作

[Authorize(Policy = "IsAdmin")]
[HttpDelete("{id}")]
public IActionResult Deleten(int id)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

经过身份验证的用户确实具有“管理员”角色声明:

在此处输入图片说明

此身份验证用户的访问令牌似乎不包含 admin 声明:

在此处输入图片说明

尝试向管理员用户请求此资源时,我收到了 403:

在此处输入图片说明

所以,如果我理解正确的话,IdentityServer 不包括管理员角色声明,因此用户无权访问资源。

是否可以配置 IdentityServer 使用的声明AddIdentityServerJwt?或者我误解了为什么这不起作用。

JKJ*_*JKJ 8

其他答案之一非常接近所讨论的特定用例,但忽略了 SPA 的要点。

首先,您必须像已经建议的那样添加 IProfileService 实现:

public class MyProfileService : IProfileService
{
    public MyProfileService()
    { }

    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        //get role claims from ClaimsPrincipal 
        var roleClaims = context.Subject.FindAll(JwtClaimTypes.Role);

        //add your role claims 
        context.IssuedClaims.AddRange(roleClaims);
        return Task.CompletedTask;
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        // await base.IsActiveAsync(context);
        return Task.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

但请继续执行以下操作:

services.AddIdentityServer()
                .AddApiAuthorization<ApplicationUser, ApplicationDbContext>()
                .AddProfileService<MyProfileService>();
Run Code Online (Sandbox Code Playgroud)

并且您的声明将在 JWT 上公开。将ClaimTypes.Role常量替换为与要公开的声明类型相对应的任何字符串。


Nan*_* Yu 5

在身份服务器端,您可以创建配置文件服务,使 IDS4role在颁发令牌时包含声明。

您可以从 ClaimsPrincipal 获取角色声明或从数据库获取角色并创建配置文件服务,例如:

public class MyProfileService : IProfileService
{
    public MyProfileService()
    { }

    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        //get role claims from ClaimsPrincipal 
        var roleClaims = context.Subject.FindAll(JwtClaimTypes.Role);

        //add your role claims 
        context.IssuedClaims.AddRange(roleClaims);
        return Task.CompletedTask;
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        // await base.IsActiveAsync(context);
        return Task.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

并在 Startup.cs 中注册:

services.AddTransient<IProfileService, MyProfileService>();
Run Code Online (Sandbox Code Playgroud)

在客户端,您应该从 JWT 令牌映射角色声明,并在AddOpenIdConnect中间件中尝试以下配置:

  options.ClaimActions.MapJsonKey("role", "role", "role");
  options.TokenValidationParameters.RoleClaimType = "role";
Run Code Online (Sandbox Code Playgroud)

然后您的 api 可以验证访问令牌并使用角色 policy 进行授权。

  • 不幸的是,我没有使用 AddOpenIdConnect 中间件,因为这是一个 SPA。我使用 AddIdentityServerJwt 将 Web API 与身份服务器结合在一起。我正在努力弄清楚如何使用 AddIdentityServerJwt 配置声明,因为它似乎没有任何配置选项 (2认同)