You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keycloak v0.17旧版令牌交换:目标端交换是否为良好实践?

Keycloak v0.17(旧版令牌交换)实践分析

背景说明

假设有两个机密客户端:client_source、client_target,分别对应各自的后端服务,client_source会向client_target转发请求。
用户拥有以下角色:
client_source -> [client_source_role_1,client_source_role_2], client_target -> [client_target_role_1]

用户通过client_source认证后,获得的访问令牌结构如下:

{
  ...
  "sub": "d9385e2f-e64c-420a-a231-80aaddfad734",
  "typ": "Bearer",
  "azp": "client_source",
  "resource_access": {
    "client_source ": {
      "roles": [
        "client_source_role_1",
        "client_source_role_2"
      ]
    }
  },
  "scope": "profile email",
  ...
}

现在需要将client_source的令牌交换为client_target的令牌,以获取用户在client_target中的角色权限。

方案一:源客户端侧执行跨客户端令牌交换

操作方式

配置允许client_source与client_target之间进行令牌交换,并为client_source授予交换权限,在client_source侧发起令牌交换请求。

交换请求

curl --request POST \
  'http://localhost:8085/auth/realms/<my realm>/protocol/openid-connect/token' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'client_id=<client_source client id>' \
  --data-urlencode 'client_secret=<client_source client secret>' \
  --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
  --data-urlencode 'subject_token=<client_source access token>' \
  --data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:access_token' \
  --data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:refresh_token' \
  --data-urlencode 'audience=<client_target client id>' 

返回令牌结构

{
  ...
  "sub": "d9385e2f-e64c-420a-a231-80aaddfad734",
  "typ": "Bearer",
  "azp": "client_source",
  "aud": "client_target",
  "resource_access": {
    "client_target ": {
      "roles": [
        "client_target_role_1"
      ]
    }
  },
  "scope": "profile email",
  ...
}

存在问题

交换后的令牌无法使用client_target的client_id/client_secret刷新,因为令牌的azp(授权方)是client_source,与刷新时使用的客户端ID不匹配,导致刷新令牌绑定到了错误的客户端。

方案二:目标客户端侧执行令牌交换

操作方式

在client_target侧发起令牌交换请求,无需额外配置客户端间的权限策略(默认允许自令牌交换)。

交换请求

curl --request POST \
  'http://localhost:8085/auth/realms/<my realm>/protocol/openid-connect/token' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'client_id=<client_source client id>' \
  --data-urlencode 'client_secret=<client_source client secret>' \
  --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
  --data-urlencode 'subject_token=<client_source access token>' \
  --data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:access_token' \
  --data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:refresh_token'

返回令牌结构

{
  ...
  "sub": "d9385e2f-e64c-420a-a231-80aaddfad734",
  "typ": "Bearer",
  "azp": "client_target",
  "resource_access": {
    "client_target ": {
      "roles": [
        "client_target_role_1"
      ]
    }
  },
  "scope": "profile email",
  "sid": "da75a8c5-b3f4-4e58-b7ed-e5fb2c190235",
  ...
}

优势

client_target应用无需知晓client_source的客户端ID,可通过自身Keycloak凭证完成交换,流程更便捷。

问题与分析

问:若源令牌仅包含源客户端所需信息且体积较小,在目标端进行令牌交换是否为良好实践?

结论:是可行的实践,但需结合场景权衡

  1. 安全性层面:

    • 方案二中client_target直接处理源令牌,减少了client_source与client_target之间的权限配置依赖,降低了跨客户端权限泄露的风险。只要源令牌本身没有敏感信息(已满足“仅包含源客户端所需信息”的前提),安全性不会打折扣。
    • 交换后的令牌azp为client_target,可正常使用自身凭证刷新,避免了方案一的刷新令牌绑定问题,减少了后续运维隐患。
  2. 可维护性层面:

    • 无需配置跨客户端令牌交换权限,减少Keycloak后台的配置工作,降低了客户端间的耦合度。后续新增或调整客户端时,无需同步修改权限策略。
    • client_target自主完成令牌交换,逻辑闭环,便于排查问题(比如令牌刷新失败、权限异常等问题可集中在client_target侧定位)。
  3. 性能层面:

    • 源令牌体积小,交换过程的网络开销和Keycloak的处理成本都很低,不会带来明显性能损耗。

综上,在源令牌信息精简、无敏感数据的前提下,目标端执行令牌交换是高效且合理的实践,既解决了方案一的刷新令牌问题,又简化了配置和依赖关系。


内容的提问来源于stack exchange,提问作者HydraMazay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 17:24:50