使用Keycloak和.NET core进行基于角色的授权

问题描述 投票:0回答:3

dotnet core 2.2.3 和 Keycloak 4.5.0 的基于角色的授权存在一些小问题。

在 Keycloak 中,我定义了“测试人员”角色和“开发人员”客户端角色,并为“管理员”用户定义了适当的角色映射。向Keycloak进行身份验证后;如果我查看 jwt.io 中的 JWT,我可以看到以下内容:

{
  "realm_access": {
    "roles": [
      "tester"
    ]
  },
  "resource_access": {
    "template": {
      "roles": [
        "developer"
      ]
    },
    ...
  },
  ...
}

在 .NET core 中,我尝试了很多方法,例如将

[Authorize(Roles = "tester")]
[Authorize(Roles = "developer")]
添加到我的控制器方法中,以及使用基于策略的授权,在我的
context.User.IsInRole("tester")
实现中检查
AuthorizationHandler<TRequirement>

如果我在身份验证处理程序中设置一些断点。当它被点击时,我可以看到“测试人员”和“开发人员”角色在

context.user.Claims
IEnumerable 下列为项目,如下所示。

{realm_access: {"roles":["tester"]}}
{resource_access: {"template":{"roles":["developer"]}}}

所以我应该能够通过验证

realm_access
集合中
resource_access
context.user.Claims
的值来成功地在身份验证处理程序中进行授权,但这需要我反序列化声明值,这看起来为 JSON 字符串。

我想必须有更好的方法,否则我做的事情不太正确。

oauth .net-core authorization keycloak
3个回答
26
投票

“AspNetCore.Authorization”需要名为 “roles” 的声明(字段)中的角色。并且此声明必须是字符串数组(多值)。您需要在Keycloak端进行一些配置。

第一种选择:

您可以更改现有的角色路径。

转到 Keycloak 管理控制台 > 客户端范围 > 角色 > 映射器 > 客户端角色

  • 将“令牌声明名称”更改为“角色”
  • 多值:True
  • 添加访问令牌:True

第二种选择:

如果您不想触及现有路径,您可以创建一个新的 Mapper 以在根处显示相同的角色。

转到 Keycloak 管理控制台 > 客户端范围 > 角色 > 映射器 > 创建

  • 名称:“根客户端角色”(或您想要的任何名称)
  • 映射器类型:“用户客户端角色”
  • 多值:True
  • 代币声明名称:“角色”
  • 添加访问令牌:True

0
投票

第四种选择:在收到票证事件中读取 JWT 的角色。这是片段:

options.Events.OnTicketReceived = ctx => 
{
   List<AuthenticationToken> tokens = ctx.Properties!.GetTokens().ToList();
   ClaimsIdentity claimsIdentity = (ClaimsIdentity) ctx.Principal!.Identity!;
                                
   foreach (AuthenticationToken t in tokens)
   {
      claimsIdentity.AddClaim(new Claim(t.Name, t.Value));
   }
        
   var access_token = claimsIdentity.FindFirst((claim) => claim.Type == "access_token")?.Value;
        
   var handler = new JwtSecurityTokenHandler();
   var jwtSecurityToken = handler.ReadJwtToken(access_token);
   JObject obj = JObject.Parse(jwtSecurityToken.Claims.First(c => c.Type == "resource_access").Value);
   var roleAccess = obj.GetValue("your_client_id")!.ToObject<JObject>()!.GetValue("roles");
   foreach (JToken role in roleAccess!)
   {
      claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role.ToString()));
   }
        
   return Task.CompletedTask;
};

0
投票

2023 年 5 月,Keycloak 推出了内置的索赔变压器。该声明转换器将采用 Keycloak 角色并将它们转换为 dotnet 可以理解的角色。它会自动添加到

服务扩展
AddKeycloakAuthentication中。

使用它的关键是在

RolesSource
中正确设置
KeycloakInstallationOptions
选项(注意,您可以通过
appsettings
进行设置)。例如,

        builder.Services.AddKeycloakAuthentication(new KeycloakAuthenticationOptions
        {
            // ... Other settings ...
            RolesSource = RolesClaimTransformationSource.Realm,
        });

目前默认为

RolesClaimTransformationSource.ResourceAccess
。对我来说,主要的解决方法是将其更改为
Realm
选项,因为这就是我的角色的来源。

© www.soinside.com 2019 - 2024. All rights reserved.