如何 read/import 从外部 IDP 到 Keycloak 的角色

How to read/import the roles from an external IDP into Keycloak

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

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

IDP配置如下:

在 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)。

有趣的是,如果在第一个领域中我创建了一个身份提供者映射器 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 显式导入到内部 IDP?或者,如果(以及如何)我可以代表用户请求一个令牌,该令牌将从该令牌中的 CentralSpringWeb 领域拥有该用户的角色,而无需显式创建角色每个用户角色的映射器。

I would like to know if it is possible to explicitly import the roles from an external IDP into an internal one? Or if (and how) can I request a token in behalf to the user that would have that users' roles from both the Central and SpringWeb Realm in the that token, without having to explicitly creating a Role Mapper for each user role.

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

回想起来,实际上 Keycloak 不提供开箱即用的自动从 外部导入所有角色的方法是有道理的 国内流离失所者。例如,如果我使用 Google 作为外部 IDP,为什么我的内部 IDP(,Keycloak)要关心 [=68= 使用的角色的确切名称]?!。最有可能的是,这些角色对内部 IDP 来说毫无意义,而当它们有意义时,它们可能有不同的名称。无论如何,对于那些例外情况,可以使用 Role Mapper 功能。

然而,为了使过程自动化一点,我创建了一个文件,将 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 中是可以预期的) 尚未在 internal IDP 上创建。