关于Keycloak跨客户端获取Access Token的技术咨询
这个场景在多客户端集成中挺常见的,我来给你梳理下具体的实现思路和步骤:
核心实现方案:令牌交换(Token Exchange)
这是Keycloak官方推荐的跨客户端令牌获取方式,基于RFC 8693标准,能直接用已有的appA令牌换取appB的访问令牌。
第一步:Keycloak客户端配置
先完成两个客户端的权限配置,确保appA有资格请求appB的令牌:
- 确保appA和appB的Access Type都设置为
confidential(如果是纯前端应用可以用public,但confidential更适合有后端的场景,安全性更高) - 进入appA的客户端设置,切换到「Advanced」标签页,在「Fine-grained OpenID Connect Configuration」里开启
Allow Token Exchange选项 - 给appA授予访问appB的权限:
- 进入Keycloak后台的「Clients」→ 选择appB
- 切换到「Client Roles」标签页,在「Client Roles」下拉框中选中appB
- 把需要的角色(比如
default-roles-你的realm名)分配给appA客户端(在「Available Roles」中选中后点击「Add selected」)
第二步:在appA中发起令牌交换请求
当用户点击按钮时,一定要由appA的后端发起请求(别在前端操作,避免泄露客户端密钥),向Keycloak的令牌端点发送POST请求,参数如下:
| 参数名 | 具体值说明 |
|---|---|
grant_type | 固定为 urn:ietf:params:oauth:grant-type:token-exchange |
subject_token | 当前用户的appA Access Token(从用户的会话中提取) |
subject_token_type | 固定为 urn:ietf:params:oauth:token-type:access_token |
audience | appB的客户端ID(明确指定要获取哪个客户端的令牌) |
client_id | appA的客户端ID |
client_secret | appA的客户端密钥(confidential客户端必填) |
示例curl请求(替换成你的实际配置):
curl -X POST \ http://your-keycloak-domain/auth/realms/your-realm/protocol/openid-connect/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange&subject_token=USER_APP_A_ACCESS_TOKEN&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token&audience=appB-client-id&client_id=appA-client-id&client_secret=appA-client-secret'
请求成功后,Keycloak会返回包含appB Access Token的响应,格式类似:
{ "access_token": "APP_B_ACCESS_TOKEN", "expires_in": 300, "token_type": "Bearer", "scope": "openid email profile" }
第三步:传递令牌给appB并验证
- appA拿到appB的Access Token后,优先用加密的POST请求或HttpOnly安全Cookie传递给appB,尽量避免用URL参数(防止令牌被日志或第三方窃取)
- appB收到令牌后,必须向Keycloak的令牌 introspection 端点验证合法性:确认令牌是Keycloak颁发、受众(
aud字段)是appB、且未过期
备选方案:静默授权码流程
如果你的场景更适合前端跳转,可以用静默认证的方式,利用用户已有的Keycloak会话直接获取appB的授权码:
- appA前端构造授权请求URL,跳转到Keycloak的授权端点:
http://your-keycloak-domain/auth/realms/your-realm/protocol/openid-connect/auth?client_id=appB-client-id&redirect_uri=appA-redirect-uri&response_type=code&scope=openid&prompt=none&state=随机字符串
- 因为用户已经在Keycloak有有效会话,Keycloak会直接重定向回appA的
redirect_uri,并携带授权码code - appA后端用授权码向Keycloak令牌端点换取appB的Access Token
- 再将令牌安全传递给appB
安全注意事项
- 所有请求必须使用HTTPS,防止令牌被窃听
confidential客户端的密钥绝对不能暴露在前端,令牌交换请求必须由后端发起- appB必须验证收到的令牌,不能直接信任任何外部传入的令牌
- 合理设置令牌的有效期,避免过长时间的授权风险
内容的提问来源于stack exchange,提问作者Nirmal
相关产品推荐
相关产品推荐

