第 12 章 配置和使用令牌交换
配置和使用令牌交换红帽构建的 Keycloak。
令牌交换是允许客户端应用程序为另一个令牌交换一个令牌的过程。在 Red Hat build of Keycloak 中,两个功能实现了令牌交换:
- 标准令牌交换:版本 2 (V2) - 此功能是完全支持的令牌交换实现,它在红帽构建的 Keycloak 服务器启动后默认启用。
- 传统令牌交换:版本 1 (V1) - 在启动红帽构建 Keycloak 服务器后,默认不启用此预览功能。
红帽构建的 Keycloak 用于令牌交换的功能如下:
- 客户端可以交换为特定客户端创建用于同一域中不同客户端的新令牌的现有红帽构建的 Keycloak 令牌。
- 客户端可以为外部令牌交换现有红帽构建的 Keycloak 令牌,如链接的 Facebook 帐户。
- 客户端可以为红帽构建的 Keycloak 令牌交换外部令牌。
- 客户端可以模拟用户。
标准令牌交换仅支持用例(1)。传统令牌交换支持四个用例,但它是一个技术预览功能。因此,建议标准令牌交换 V2,因为它被支持,并将在以后维护。传统令牌交换对最后三个用例很有用,但可能不向后兼容未来的红帽构建的 Keycloak 版本。您还可以启用令牌交换功能,并将它们一起使用。例如,您可以将 V2 提供的内部内部交换与 V1 支持的其他用例一起使用。如需了解更多详细信息,请参阅此 令牌交换比较。
如果您仍然需要旧的令牌交换功能,则还需要启用 Fine-grained admin permissions version 1 (FGAP:v 1),因为版本 2 (FGAP:v2) 不支持令牌交换权限。这是因为 token-exchange 是概念上并不是"管理员"权限,因此没有计划将令牌交换权限添加到 FGAP:v2。
12.1. 标准令牌交换 复制链接链接已复制到粘贴板!
红帽构建的 Keycloak 中的标准令牌交换实现了 Token Exchange 规格。它允许客户端应用程序交换为签发的新令牌到触发令牌交换请求的客户端的特定客户端创建的 Keycloak 令牌的现有红帽构建。两个客户端都必须位于同一域中。
12.1.1. 令牌交换流 复制链接链接已复制到粘贴板!
考虑这个典型的令牌交换流:
-
用户使用红帽构建的 Keycloak SSO 进行身份验证到客户端应用
初始客户端。该令牌将发布到初始客户端。 -
客户端
initial-client可能需要使用 REST 服务requester-client,这需要身份验证。因此,initial-client使用令牌将访问令牌从第 1 步发送到requester-client 为了服务请求,
requester-client可能需要调用另一个服务target-client。但是,它可能无法使用从initial-client发送到令牌。例如:- 令牌的权限或范围不足。
-
target-client没有被指定为令牌 audience;令牌旨在用于调用requester-client。 令牌必须具有许多权限,因此
requester-client可能不想与target-client共享。这样的情形可能是调用令牌交换的原因。
requester-client可能需要向红帽构建的 Keycloak 服务器发送令牌交换请求,并使用第 1 步中的原始令牌作为 主题令牌,并为 请求的 另一个令牌交换它。
-
请求的令牌 返回到
requester-client。此令牌现在可以发送到target-client。 -
target-client可以满足请求,并将响应返回给requester-client。然后,requester-client可以跟进,并将响应返回在第 2 步中的请求。
令牌交换存在许多其他用例,但前面的示例是最典型的。
12.1.1.1. 令牌交换请求示例 复制链接链接已复制到粘贴板!
以下是域 test 中客户端 请求者-client 的令牌交换请求示例。请注意,subject_token 是向 initial-client 发布的访问令牌:
令牌交换响应示例可能类似如下:
12.1.2. 如何启用令牌交换 复制链接链接已复制到粘贴板!
对于标准令牌交换,token-exchange-standard:v2 会被默认启用。但是,您还需要为应当发送 令牌交换请求的客户端启用标准 令牌交换交换机,如 上例中的 requester-client。请注意,requester-client 必须是一个机密客户端。另外,与其他授权请求一样,令牌交换请求必须通过为客户端配置的适当 客户端验证方法进行身份验证。
图 12.1. 启用令牌交换
12.1.3. 请求和响应参数 复制链接链接已复制到粘贴板!
参数与 Token Exchange 规格 一致,如下:
- grant_type
-
必需。参数的值必须是
urn:ietf:params:oauth:grant-type:token-exchange。 - subject_token
- 必需。代表要发出请求的人,代表方身份的安全令牌。
- subject_token_type
-
必需。此参数是在
subject_token参数中传递的令牌类型。当使用标准令牌交换时,必须为urn:ietf:params:oauth:token-type:access_token,因为红帽构建的 Keycloak 不支持标准令牌交换的其他类型的。 - requested_token_type
-
可选。此参数代表了客户端要交换的令牌类型。在本发行版本中,只支持 oauth 和 OpenID Connect 令牌类型。默认值为
urn:ietf:params:oauth:token-type:access_token。如果请求了请求给requester-client的 ID 令牌,则另一个可能的值是urn:ietf:params:oauth:token-type:id_token。可能的值可能是urn:ietf:params:oauth:token-type:refresh_token; 在这种情况下,您将在响应中接收访问令牌和刷新令牌。但是,如果在Standard Token Exchange 客户端配置选项中启用了 Allow refresh token,则允许刷新令牌,如 标准令牌交换 部分中指定的。 - scope
-
可选。此参数代表客户端请求的以空格分隔的 OAuth 和 OpenID Connect 范围集合。您可以使用
requester- client 的可选客户端范围。如需了解更多详细信息,请参阅 范围和受众。省略此参数意味着,只会有效地使用 Default 客户端范围。 - 受众
-
可选。audience 指定客户端的
client_id,它应当用作令牌受众。在上例中, 它可以是target-client。这个参数的多个值是允许的,这意味着您希望令牌包含多个不同服务的requester-client使用。例如audience=target-client1&audience=target-client2可以在请求中使用。有关 范围和受众的部分中的更多详细信息。
JSON 格式返回成功响应。它包含类似的参数,如来自其他授权的响应。以下是更显著参数的一些令牌交换细节:
- access_token
-
请求的访问令牌。请注意,如果请求指定了
requested_token_type=urn:ietf:params:oauth:token-type:id_token,则此参数实际上可能包含 ID 令牌而不是访问令牌。此行为根据 令牌交换规格。 - refresh_token
-
刷新令牌。只有在使用
requested_token_type=urn:ietf:params:oauth:token-type:refresh_token时包括它,且客户端已经启用了从令牌交换发出刷新令牌 - issued_token_type
-
发布的令牌类型。值与请求中使用的
requested_token_type相同。 - token_type
-
通常,如果发布的令牌类型是访问令牌或刷新令牌,则通常是
Bearer。如果请求的 ID 令牌,则值为N_A
12.1.4. 范围和受众 复制链接链接已复制到粘贴板!
令牌交换请求中的 scope 参数与其他授予的含义相同。这个参数是可选的。当省略时,请求中使用的有效客户端范围是 requester- client 的 Default 客户端范围。使用此参数时,有效的客户端范围是默认范围和可选 客户端范围
默认情况下,使用的客户端范围将根据 Audience 文档 中指定的已用客户端范围和客户端角色将使用者添加到令牌的声明中。
audience 参数可用于过滤受众,以便 aud 声明将仅包含 audience 参数指定的使用者。类似地,令牌中的客户端角色将被过滤,令牌将仅具有由 audience 参数指定的客户端的客户端角色。
此外,audience 参数也可用于可能过滤客户端范围。它的工作方式与 Client 范围权限类似。如果客户端范围不包含任何客户端角色(例如,它包含零角色或仅包含 realm 角色),则不会对客户端范围进行额外的过滤。但是,如果客户端范围包含任何客户端角色映射,它必须包含 audience 参数所请求的客户端的一些客户端角色。还包括了复合角色以供考虑。如果客户端范围不包含 audience 所请求的客户端的客户端角色,则会过滤客户端范围。
audience 参数可用于过滤来自已用客户端范围的受众。但是,此参数不会添加更多受众。当省略 audience 参数时,不会发生过滤。因此,audience 参数有效用于"关闭"令牌,以确保它只包含请求的受众。但是,scope 参数用于添加可选的客户端范围,因此可用于"upscoping"并添加更多范围。
12.1.4.1. 例子 复制链接链接已复制到粘贴板!
下面是一些示例,以更好地说明范围和受众的行为。
假设有带有以下内容的域:
-
带有客户端角色
target-client1-role的客户端target-client1 -
带有客户端角色
target-client2-role的客户端target-client2 -
带有客户端角色
target-client3-role的客户端target-client3 -
客户端范围
default-scope1。此客户端范围具有客户端角色target-client1/target-client1-role的角色范围映射 -
客户端范围
optional-scope2.此客户端范围具有客户端角色target-client2/target-client2-role的角色范围映射 -
客户端请求
程序-客户端范围为default-scope1,它添加了默认客户端范围,范围optional-scope2添加为可选客户端范围 -
经过身份验证的用户,该用户是
target-client1-role和target-client2-role的成员
上面的设置意味着,使用范围 default-scope1 会将 audience target-client1 添加到令牌中,并使用 optional-scope2 将添加 audience target-client2。这是因为受众 文档 所描述的受众解析。
12.1.4.1.1. 示例 1 复制链接链接已复制到粘贴板!
令牌交换请求通过 scope=optional-scope2 和没有 audience 参数发送:
不对听众进行过滤。范围和受众将作为任何其他授予的情况解决,如 客户端范围和 Audience 文档部分中所述。响应令牌将与此类似(对于此示例为 brevity 省略的声明并不有帮助):
12.1.4.1.2. 示例 2 复制链接链接已复制到粘贴板!
使用 scope=optional-scope2 和 audience=target-client2发送的令牌交换请求
与前面的示例相同,但 target-client1 audience 和 client 角色过滤自 audience 参数,但仅包含此 target-client2 客户端。客户端范围 default-scope1 也会被过滤,因为它包含一些客户端角色,但同时,它不包含所请求的 audience 客户端 target-client2 的任何客户端角色。因此,令牌应该如下:
12.1.4.1.3. 示例 3 复制链接链接已复制到粘贴板!
令牌交换请求通过 scope=optional-scope2 和 audience=target-client2&audience=target-client3发送
target-client3 不是令牌 audience 的一部分,因为用户没有任何角色。因此,由于某些请求的受众不可用,请求将被拒绝。
如令牌交换规范中所述,最好尽可能减少令牌范围,并且仅使用所需的受众。理想情况下,使用单个受众。此策略提高了允许请求的概率。
如果您的部署具有多个不同范围和受众的复杂部署,则以适当的方式对部署进行建模可能具有挑战性。考虑使用 Client range evaluate 选项卡 来测试令牌是否为给定用户以及给定范围和 audiences 集合的预期。
12.1.5. 令牌交换 - 其他详情 复制链接链接已复制到粘贴板!
这些额外的点明确令牌交换的行为。
- 公共客户端不支持发送令牌交换请求。当公共客户端可以以较少的范围交换令牌时,V1 对公共客户端有一些非常有限的支持。此用例可通过刷新令牌授权来替代。
-
发送到令牌交换端点的
subject_token必须将请求者客户端设置为aud声明中的 audience。否则,请求将被拒绝。唯一的例外是,如果客户端交换自己的令牌,即客户端向其发出了自己的令牌。交换自身对于减少令牌范围/范围可能很有用,或者过滤不需要的令牌受众等。 - consents - 如果请求者客户端启用了 Consent 需要,则只有在用户已授予所有请求范围的同意时才允许令牌交换
- 标准令牌交换不需要 细粒度 admin 权限(FGAP)。我们计划未来与 FGAP 集成,但该集成可能适用于所有补贴。它不仅特定于令牌交换,因为它在令牌交换 V1 中。
-
可以将令牌交换与客户端 策略 集成。此集成可用于解决某些用例。例如,如果客户端
请求者-客户端通过发送请求,则请考虑拒绝令牌交换请求的用例。在本例中,创建客户端策略条件以及scope=some-confidential-scopeclient-scope、grant-type和client-roles的组合条件会很有用。 -
只有在客户端在 Standard Token Exchange 中将 switch Allow refresh token 设置为非非值时,
才允许请求刷新令牌。交换机包括在 OpenID Connect Compatibility Modes 部分的 OIDC 客户端 Advanced 标签页的 Admin Console 中。交换机的另一个可用值为 Same 会话,这意味着只有在刷新令牌可以使用与主题令牌相同的用户会话时,才允许刷新令牌。如果该主题令牌来自 Transient 会话 或从 离线会话中,则不允许请求刷新令牌。同样,不允许请求离线令牌(使用scope=offline_access)。
图 12.2. 在令牌交换中启用刷新令牌
12.1.5.1. 吊销 复制链接链接已复制到粘贴板!
假设向客户端 initial-client 发出了一个主题令牌 access-token1,以下与令牌撤销相关的注意事项:
-
在这种情况下,当将
access-token1与客户端请求er-client 的access-token2交换时,access-token1的撤销不会撤销access-token2。支持用于访问令牌的"撤销链"意味着相当大的开销。因此,管理员必须确保访问令牌已短,并在一段时间后自动撤销。 对于这种情况,当将
access-token1交换为客户端requester-client的refresh-token2时,我们会尝试支持撤销链。这意味着:-
撤销
access-token1将撤销也会撤销refresh-token2。此外,这将从用户会话中删除客户端请求者-客户端的客户端会话,因此此用户会话中请求者-客户端的所有刷新令牌都将有效撤销 -
如果
refresh-token2及其相关访问令牌用于进一步与不同的客户端进行令牌交换,则access-token1的撤销也会撤销这些后续令牌交换。换句话说,将撤销交换令牌的整个"链"。 -
请注意,当调用撤销端点时,访问令牌应该有效。如果您在原始
access-token1过期时没有有效的访问令牌,您可能会在同一用户会话中对同一客户端发出的另一个访问令牌。应撤销来自"chain"的交换令牌,如refresh-token2和其他令牌。
-
撤销
12.1.6. 标准令牌交换和旧令牌交换的比较 复制链接链接已复制到粘贴板!
虽然前面部分详细介绍了标准和旧令牌交换,但以下是比较两个令牌交换方法的整体摘要。
| 功能 | 标准令牌交换 V2 | 传统令牌交换 V1 |
|---|---|---|
| 内部令牌交换 | 支持。根据 rfc8693 实施 | 预览支持.rfc8693 的松散实施。建议使用 V2 替代 |
|
allowed | 仅限访问令牌类型 | 仅限内部令牌类型,JWT 用于外部内部场景 |
|
Allowed | 访问令牌(默认)、刷新令牌、ID 令牌 | 访问令牌、刷新令牌(默认)、SAML2 断言 |
|
行为 | 与其他补贴一致。scope 参数意味着请求客户端的可选范围,后者发送令牌交换请求 | scope 参数基于由 audience 参数指定的"目标"客户端的范围。只支持 Downscoping |
|
| 根据规格支持更多值。可用于缩小可用受众,仅保留请求的受众。根据所需的目标受众有效地缩减令牌 | 支持单个受众价值.audience 参数有效地向客户端发出令牌,并使用该客户端的范围 |
| 公共客户端 | 不可用。由 V1 实施的 Downscoping 可以被刷新令牌授权替代 | 仅适用于交换客户端本身的令牌。有效地缩减支持 |
| 同意 |
只要已授予用户同意,则允许具有 | 不允许具有 Consent 所需的客户端 |
| 授权 |
验证请求者客户端必须在 | 基于精细的 admin 权限版本 1 |
| 吊销链 | 不适用于访问令牌。可用于刷新令牌 | 无法访问或刷新令牌 |
| 每个 rfc8693 的委派 | 尚不支持 | 不支持 |
| 每个 rfc8693 的资源参数 | 尚不支持 | 不支持 |
| 联邦令牌交换 | 尚未实施 | 作为技术预览实现 |
| 主题模拟(包括直接利用的模拟) | 尚未实施 | 作为技术预览实现 |