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 字符串。
我想必须有更好的方法,否则我做的事情不太正确。
“AspNetCore.Authorization”需要名为 “roles” 的声明(字段)中的角色。并且此声明必须是字符串数组(多值)。您需要在Keycloak端进行一些配置。
第一种选择:
您可以更改现有的角色路径。
转到 Keycloak 管理控制台 > 客户端范围 > 角色 > 映射器 > 客户端角色
第二种选择:
如果您不想触及现有路径,您可以创建一个新的 Mapper 以在根处显示相同的角色。
转到 Keycloak 管理控制台 > 客户端范围 > 角色 > 映射器 > 创建
第四种选择:在收到票证事件中读取 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;
};
2023 年 5 月,Keycloak 推出了内置的索赔变压器。该声明转换器将采用 Keycloak 角色并将它们转换为 dotnet 可以理解的角色。它会自动添加到
服务扩展的
AddKeycloakAuthentication
中。
使用它的关键是在
RolesSource
中正确设置 KeycloakInstallationOptions
选项(注意,您可以通过 appsettings
进行设置)。例如,
builder.Services.AddKeycloakAuthentication(new KeycloakAuthenticationOptions
{
// ... Other settings ...
RolesSource = RolesClaimTransformationSource.Realm,
});
目前默认为
RolesClaimTransformationSource.ResourceAccess
。对我来说,主要的解决方法是将其更改为 Realm
选项,因为这就是我的角色的来源。