【问题标题】:How to handle array claim values in ASP.net Core using OIDC如何使用 OIDC 在 ASP.net Core 中处理数组声明值
【发布时间】:2022-01-20 18:08:29
【问题描述】:

我正在运行 IdentityServer4 的 Skorubas 实现 https://github.com/skoruba/IdentityServer4.Admin

由于某种原因,我最终收到了一个带有声明类型“角色”的角色声明和一个包含当前用户所有角色的数组值: ["SkorubaIdentityAdminAdministrator","MyRole"]

现在,如果我想使用 Authorize-attribute 保护“页面”: [授权(Role="MyRole")]

这总是会导致访问被拒绝,因为 ASP.net Core 需要多个具有相同声明类型的声明,所以在这种情况下,声明将是

类型 | 价值

角色:“SkorubaIdentityAdminAdministrator”

角色:“我的角色”

是否有任何“最佳实践”来解析收到的声明并在它们被 ASP.net 核心处理之前重新格式化它们,或者告诉 OpenIdConnect 扩展将数组格式作为多个声明处理?

【问题讨论】:

    标签: asp.net-core openid-connect roles claims


    【解决方案1】:

    在 JWT 中收到的声明通常可以是数组或对象以及简单类型。使用 .NET 属性进行授权时处理此问题的方法是通过策略。

    它们非常简单,this Curity tutorial 有一些示例。此代码 sn-p 显示整个 ClaimsPrincipal 可用于策略,因此您可以在用例中轻松处理数组声明:

    options.AddPolicy("lowRisk", policy =>
            policy.RequireAssertion(context =>
                context.User.HasClaim(claim => 
                    claim.Type == "risk" && Int32.Parse(claim.Value) < 50
                )
            )
    );
    
    [HttpGet("lowrisk")]
    [Authorize( Policy = "lowRisk")]
    public IActionResult LowRisk()
    {
        return Ok();
    }
    

    【讨论】:

      【解决方案2】:

      事实证明,您可以创建自己的 ClaimActions,在上面的示例中,我必须执行以下操作:

      首先..创建一个新类:

      public class RoleClaimAction : ClaimAction
      {
          private const string RoleClaimType = "role";
      
          public RoleClaimAction() : base(RoleClaimType, ClaimValueTypes.String)
          {
          }
          
          public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
          {
              //Map array of roles to separate role claims
              var roles = userData.TryGetStringArray(RoleClaimType)?.ToList();
              if (roles!.Any())
              {
                  foreach (var role in roles!)
                  {
                      AddRoleClaim(identity, role, issuer);
                  }
      
                  return; 
              }
      
              //If we only have one role (not an array), add it as a single role claim
              var singleRole = userData.TryGetString(RoleClaimType);
              if(!string.IsNullOrEmpty(singleRole))
                  AddRoleClaim(identity, singleRole, issuer);
          }
      
          private void AddRoleClaim(ClaimsIdentity identity, string role, string issuer)
          {
              identity.AddClaim(new Claim(JwtClaimTypes.Role, role, ClaimValueTypes.String, issuer));
          }
      }
      

      这将简单地验证用户有一个名为角色的声明,并将数组值重新映射到单独的角色声明,然后“挂钩”到身份验证框架中。

      要添加您的 ClaimAction,只需将其添加到您的 OpenIdConnectOptions 中:

      options.ClaimActions.Add(new RoleClaimAction())
      

      现在使用角色授权属性,并且 User.IsInRole(string) 应该可以正常工作。

      【讨论】:

        猜你喜欢
        • 2020-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-31
        • 2010-09-08
        • 2018-01-26
        • 2016-12-25
        相关资源
        最近更新 更多