惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
博客园 - 司徒正美
Last Week in AI
Last Week in AI
博客园 - 聂微东
Jina AI
Jina AI
月光博客
月光博客
爱范儿
爱范儿
美团技术团队
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hugging Face - Blog
Hugging Face - Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 叶小钗
T
Tailwind CSS Blog
博客园 - 【当耐特】
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Apple Machine Learning Research
Apple Machine Learning Research
有赞技术团队
有赞技术团队
罗磊的独立博客
小众软件
小众软件
雷峰网
雷峰网
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Visual Studio Blog

博客园 - 张占岭

keycloak~缓存对象的介绍与作用 wso2-apim-mcp2改版分析 mcp1和mcp2对比 为什么前端项目使用ts比js要多了 多个IDP的用户联合方案的分析 apisix~forward-auth外部认证 apisix~response-rewrite响应头重写 springboot~关于构造方法注入和字段注入的选择 apisix~OpenResty各阶段的介绍 keycloak~aud受众字段的作用及如何生成 wso2~关于workbuddy中mcp在wso2中的授权端点 k8s~避免调度资源碎片化 WEB安全~csrf介绍 WEB安全~DPoP的介绍 WEB安全~csp的介绍 什么是中间人攻击 WEB安全~xss的介绍 k8s~pod资源限制和JVM的XMX配置 关于对wso2和keycloak的token交换的调研 keycloak~实现OAuth 2.0 Token Exchange backstage~实体的介绍及它们的关系 backstage~openapi的接入与protobuf的对比 backstage~将java服务添加到backstage backstage~对接github和gitlab backstage~开始一个backstage应用 apisix~graphQL的支持 wso2几个核心项目介绍 docker~BuildKit的介绍 k8s~secret资源的使用 算法~时间戳计算两个日期是否为同天同时同分
keycloak~通过用户ID直接置换token
张占岭 · 2026-09-17 · via 博客园 - 张占岭

Keycloak Token Exchange + Impersonation(运维配置)

门户 GET /kc/exchange-token 新流程:

  1. 用请求头里的 WSO2 应用 access_token 调 mcp-admin:POST /internal/wso2/token/authz-user → 得到 kcUserId(来自 idn_oauth2_access_token.AUTHZ_USER
  2. 用 Keycloak 客户端 wso2client_credentials 拿到服务账号 token
  3. 再用 Token Exchange,带 requested_subject={kcUserId},签发该用户的 KC access_token

因此 不要求 WSO2 应用 token 带 openid scope,但要求 Keycloak 客户端具备 Service Account + Token Exchange(用户模拟) 权限。

以下以客户端 ID wso2、Realm fabao 为例(与 application-*.ymlkeycloak.client-id 一致)。


一、客户端基础开关

登录 Keycloak Admin Console → Realm fabaoClientswso2

建议值
Client authentication On
Authentication flow / Standard flow 按现有对接保留
Service accounts roles On(必须,用于 client_credentials)
Direct access grants 可不依赖
Valid redirect URIs / Web origins 按现有配置

保存后,在 Credentials 页确认 client-secret 与各环境 KEYCLOAK_WSO2_CLIENT_SECRET / yml 一致。


二、开通 Token Exchange(推荐:Permissions 模式,适用于多数现网 KC)

不同 Keycloak 大版本菜单位置略有差异,目标是:允许客户端 wso2 用自己的服务账号 token,对任意(或指定)用户做 requested_subject 交换。

2.1 开启客户端 Permissions

  1. Clients → wso2Permissions(或 Authorization)
  2. Permissions enabled 设为 On
  3. 等待出现权限列表(含 token-exchange、可能还有 impersonate 等)

2.2 配置 token-exchange 权限

  1. 打开权限 token-exchange
  2. Decision Strategy:Affirmative(或按现网规范)
  3. 关联一条 Client Policy
    • 新建 Policy → 类型 Client
    • Clients:勾选 wso2
    • Logic:Positive
  4. 将该 Policy 绑到 token-exchange Permission 并 Save

image

2.3 配置用户 Impersonation(requested_subject 必需)

requested_subject 属于「用 A 的 token 换 B 用户的 token」,除 token-exchange 外通常还要 impersonation

方式 A(常用,粒度到用户权限):

  1. Realm → Users → 任意用户 → Permissions(需先在 Realm Settings 开启 Users permissions;部分版本在 Realm settings → User registration / Permissions
  2. 或:Realm → Permissions / Authorization 中找到用户 impersonation 相关权限
  3. 更稳妥的现网做法见 方式 B

方式 B(服务账号角色,配置简单,权限较大):

  1. Clients → wso2Service account roles
  2. Client roles 来源选 realm-management
  3. 分配角色:
    • impersonation(必须)
    • 若列表里还有与 token-exchange 相关的角色可一并勾选(视版本而定)
  4. Save

方式 B 权限面更大(可模拟 realm 内用户),仅限受信的内部客户端 wso2,密钥严格保管。

image

2.4(可选)Audience / Client scope

若换出的用户 token 需要特定 audience 或 scope(门户后续 jwt-bearer 进 APIM 依赖 claim):

  • Clients → wso2Client scopes:保证默认 scope 含业务所需(至少 openid,与 yml keycloak.scope 一致)
  • Token Exchange 请求里门户已传 scope=openid(可配置)

三、自检(运维验证)

{KC_TOKEN_URI}{CLIENT_ID}{CLIENT_SECRET}{KC_USER_ID} 换成实际值。

3.1 client_credentials

curl -s -X POST '{KC_TOKEN_URI}' \
  -u '{CLIENT_ID}:{CLIENT_SECRET}' \
  -d 'grant_type=client_credentials' \
  -d 'scope=openid'

应返回 access_token。记下为 ACTOR_TOKEN

3.2 token-exchange + requested_subject

curl -s -X POST '{KC_TOKEN_URI}' \
  -u '{CLIENT_ID}:{CLIENT_SECRET}' \
  -d 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
  -d 'subject_token={ACTOR_TOKEN}' \
  -d 'subject_token_type=urn:ietf:params:oauth:token-type:access_token' \
  -d 'requested_token_type=urn:ietf:params:oauth:token-type:access_token' \
  -d 'requested_subject={KC_USER_ID}' \
  -d 'scope=openid'

成功:返回用户 access_token;解码 JWT 后 sub(或等价用户标识)应为该用户。

常见失败:

现象 处理
Client not allowed to exchange / not allowed to impersonate 补全 2.2 / 2.3
Client not enabled for service accounts 打开 Service accounts roles
Invalid user credentials / user not found 确认 AUTHZ_USER / kcUserId 是 Realm 内真实用户 ID(UUID)或用户名,与 Keycloak 用户匹配
unauthorized_client client-secret 或 client-id 错误