12.2. 内部令牌交换
使用内部令牌进行令牌交换,您已将令牌 mint 到一个特定的客户端,并且您想要为不同的目标客户端交换此令牌。您为什么要执行此操作?当客户端具有对其自身的令牌 mint 时,通常会发生这种情况,并且需要对访问令牌中需要不同声明和权限的其他应用程序发出额外的请求。如果您需要执行"权限降级",您可能需要进行"权限降级",因为应用程序需要在不太信任的应用程序上调用,而您不想传播当前的访问令牌。
12.2.1. 为交换授予权限
希望为不同客户端交换令牌的客户端需要在 Admin 控制台中获得授权。您需要在目标客户端中定义令牌交换权限。
图 12.1. 目标客户端权限

流程
将" 启用" 的权限切换为 On。
图 12.2. 目标客户端权限
该页面显示 token-exchange 链接。
单击该链接,以开始定义权限。
这时将显示此设置页面。
图 12.3. 目标客户端交换权限设置
- 在屏幕顶部的面包屑导航栏中点 Client details。
- 为这个权限定义策略。
- 在屏幕顶部的面包屑导航栏中点 Authorization。
- 为这个权限定义策略。
- 点 Policies 选项卡。
点 Create policy 按钮创建 客户端 策略。
图 12.4. 客户端策略创建
- 在作为请求令牌交换的经过身份验证的用户中输入。
创建此策略后,返回到目标客户端的 token-exchange 权限,并添加您刚才定义的客户端策略。
图 12.5. 应用客户端策略
您的客户端现在有调用的权限。如果不正确这样做,如果您尝试进行交换,您将会收到 403 Forbidden 响应。
12.2.2. 发出请求
当客户端针对另一个客户端为目标的令牌交换现有令牌时,您可以使用 audience
参数。此参数必须是您在管理控制台中配置的目标客户端的客户端标识符。
curl -X POST \ -d "client_id=starting-client" \ -d "client_secret=the client secret" \ --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ -d "subject_token=...." \ --data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:refresh_token" \ -d "audience=target-client" \ http://localhost:8080/realms/myrealm/protocol/openid-connect/token
curl -X POST \
-d "client_id=starting-client" \
-d "client_secret=the client secret" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=...." \
--data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:refresh_token" \
-d "audience=target-client" \
http://localhost:8080/realms/myrealm/protocol/openid-connect/token
subject_token
参数必须是目标域的访问令牌。如果您的 requested_token_type
参数是刷新令牌类型,则响应将同时包含访问令牌、刷新令牌和过期。以下是您从此调用返回的示例 JSON 响应:
如果没有设置 audience
参数,则参数的值默认为提交令牌交换请求的客户端。
与机密客户端不同,不允许公共客户端使用来自其他客户端的令牌执行令牌交换。如果您要传递 subject_token
,签发令牌的(机密)客户端应与发出请求的客户端匹配,或者如果向其他客户端发出,则使请求的客户端应设置为令牌的使用者。
如果您明确设置目标 audience
(客户端与发出请求的客户端不同),您应确保为客户端集配置了 token-exchange
范围权限,设置 audience
权限以允许客户端成功完成交换。
{ "access_token" : "....", "refresh_token" : "....", "expires_in" : 3600 }
{
"access_token" : "....",
"refresh_token" : "....",
"expires_in" : 3600
}