如何从外部 IDP 读取/导入角色到 Keycloak

Posted

技术标签:

【中文标题】如何从外部 IDP 读取/导入角色到 Keycloak【英文标题】:How to read/import the roles from an external IDP into Keycloak 【发布时间】:2021-02-14 10:38:03 【问题描述】:

我有一个使用 Keycloak 11.0.2 保护的 Spring Boot 应用程序,我的 Keycloak 设置如下:

一个名为Central 的领域,角色为CentralWebUser,客户端为SpringWeb。客户有 Access Type : public 并且只启用了一个流,即Standard Flow Enabled Valid Redirect URIs : http://localhost:8000/* 一个名为 SpringApp 的 2ª 领域,角色 WebUser 和客户端 spring_brokering 一个名为springuser 的用户具有领域角色WebUser 客户端spring_brokering只有Standard Flow Enabled设置为ON,Valid Redirect URIs:http://localhost:8080/*,和Access TypeConfidential

第二个领域是第一个领域的 IDP。因此,要登录用户转到Central 登录页面并选择IDP SpringAppIDP

IDP配置如下:

alias : SpringAppIDP,除了启用的选项外,其他所有内容均为 OFF 授权 URL、令牌 URL 等设置为来自 SpringApp 端点的 URL(e.g., Authorization URL : http://127.0.0.1:8080/auth/realms/SpringApp/protocol/openid-connect/auth) 客户端 ID 和客户端密码分别是 spring_brokering 及其密码。

在 Spring 方面,我有以下属性值得一提:

server.port                         = 8000
keycloak.realm                      = Central
keycloak.auth-server-url            = http://localhost:8080/auth
keycloak.ssl-required               = external
keycloak.resource                   = SpringWeb
keycloak.public-client=true

keycloak.security-constraints[0].authRoles[0]=WebUser
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/services/*

当我访问 http://127.0.0.1:8080/services 时,我被重定向到 Keycloak Central 领域登录页面,然后我单击 SpringAppIDP 并输入用户名 springuser 及其密码。登录成功,但是我得到了一个access denied,这意味着用户springuser没有WebUser的角色。但是,该角色是在第二个领域内分配给该用户的(SpringApp)。

有趣的是,如果在第一个 Realm 中创建身份提供者 Mapper External Role to Role(在 IDP SpringAppIDP 配置中)将 WebUser 的外部角色映射到 CentralWebUser 并将 spring 属性更改为:

keycloak.security-constraints[0].authRoles[0]=CentralWebUser
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/services/*

我能够登录,这意味着 Keycloak 知道用户拥有WebUser 角色,因此将该角色映射到CentralWebUser 角色。

我想知道是否可以将角色从外部 IDP 显式导入到内部?或者,如果(以及如何)我可以代表用户请求一个令牌,该令牌将拥有来自该令牌中 CentralSpringWeb 领域的用户角色,而无需为每个用户显式创建角色映射器角色。

【问题讨论】:

【参考方案1】:

我想知道是否可以显式导入角色 从外部 IDP 变成内部 IDP?或者如果(以及如何)我可以 代表将拥有该用户的用户请求令牌 该令牌中来自 Central 和 SpringWeb Realm 的角色, 无需为每个用户显式创建角色映射器 角色。

没有为每个用户角色显式创建角色映射器,我发现的唯一解决方案是扩展 Keycloak 代码;这有明显的缺点。

回想起来,实际上 Keycloak 不提供开箱即用的自动从外部 IDP 导入所有角色的方法是有道理的。例如,如果我使用 Google 作为外部 IDP,为什么我的内部 IDP(,Keycloak)应该关心 Google 使用的角色的确切名称?!。最有可能的是,这些角色对于内部 IDP 来说毫无意义,并且当它们有意义时,它们可能具有不同的名称。无论如何,对于这些例外情况,可以使用角色映射器功能。

不过,为了使流程自动化一点,我创建了一个文件,将 internal IDP 的角色映射到 external IDP,例如:

ROLE A | ROLE B
....

我还有一个 JSON 文件,其中包含角色映射器示例的 模板,其中一些标签随后将被替换(例如字段roleexternal.role )。

通过脚本,我读取具有角色之间映射的文件,并使用Keycloak Admin REST API 创建角色、映射器等。

我使用的逻辑如下:

如果 external IDP 中不存在该角色,我只是跳过并假设这是一个错误; 如果internal IDP 中不存在该角色,我将其创建为领域角色;为此,我使用端点POST /realm/roles 最后,我使用端点POST /realm/identity-provider/instances/alias/mappersJSON 模板角色映射器文件的内容创建角色映射器(相应地替换了它的标签)。

不在external IDP 中创建领域角色的理由是,来自external IDP 的所有角色都应该已经从LDAP 加载。对于 internal IDP,我确实创建了,因为对于映射 1 到 1,LDAP 中的角色(加载到 external IDP)可能尚未创建内部 IDP。

【讨论】:

以上是关于如何从外部 IDP 读取/导入角色到 Keycloak的主要内容,如果未能解决你的问题,请参考以下文章

Keycloak IdP SAML2 将 XML 元数据导出到 SP

IdentityServer4 ADFS 外部不返回角色

Spring SAML 2.0 - 导入 IDP 的本地元数据 - MetadataProviderException

Keycloak、PKCE 和外部 IDP

C语言如何将外部数据导入?

为啥我的 AWS 代入角色未被授权执行 cognito-idp:AdminGetUser?