Keycloak代理登出时未向外部IdP发送登出请求问题排查
Keycloak代理与外部IdP登出同步问题排查求助
场景概述
- 架构:Keycloak实例KC1部署在应用服务器(作为代理),另一服务器上的KC2作为外部身份提供商,两者版本均为26.0.1,通过SSL通信,已配置密钥库与信任库
- KC1启用特性
--features=transient-users,修改默认首次代理登录流程,禁用「Review Profile」;KC2的IdP定义中开启「Do not store users」,该部分配置正常生效
登录流程现状
用户访问应用URL:https://myserver1:45002/myApp(SpringBoot后端+Angular前端),应用application.yml配置如下:
issuer-uri: https://myserver1:45003/realms/myRealm scope: openid client-id: myClientApp
流程详情:
- 应用将用户重定向至KC1登录页:
https://myserver1:45003/realms/myRealm/protocol/openid-connect/auth... - 可选登录方式:
- KC1本地登录:登录成功后重定向至应用,KC1创建会话,浏览器生成授权/刷新令牌;登出时令牌吊销、KC1会话删除,符合预期
- KC2外部登录:跳转至KC2登录页完成认证后返回应用,KC1生成临时用户会话,KC2生成常规用户会话,登录流程正常
核心问题
通过KC2登录后,应用登出时仅销毁KC1的临时会话、清除浏览器令牌,但KC2的用户会话仍处于活跃状态,需要实现登出时同步销毁KC2会话。已配置所有可用backchannel参数,但KC1未向KC2发送登出请求;开启TRACE级别日志后,KC2无相关日志活动,浏览器控制台与应用后端均无错误。
现有配置明细
1. KC1的myRealm中myClientApp客户端配置
- Client ID: myClientApp
- Root URL:
https://myserver1:45002/myApp - Home URL:
https://myserver1:45002/myApp - Valid redirect URIs:
https://myserver1:45002/* - Valid post logout redirect URIs:
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/logout - Web origins:
https://myserver1:45002/ - Admin URL:
https://myserver1:45002/myApp - Authentication flow: 启用Standard flow和Direct access grants
- Logout settings:
- Front channel logout: OFF
- Backchannel logout URL:
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/logout - Backchannel logout session required: ON
- Backchannel logout revoke offline sessions: ON
2. KC1身份提供商中KC2的IdP定义
- Redirect URI:
https://myserver1:45003/realms/myRealm/broker/KC2-IdP/endpoint - Alias/Display name: KC2-IdP
- Authorization URL:
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/auth - Token URL:
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/token - Logout URL:
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/logout - User Info URL:
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/user-info - Issuer:
https://myserver2:45003/realms/myRealm-myServer2/ - Validate Signature: ON
- USE JWKS URL: ON
- JWKS URL:
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/certs - Use PKCE: OFF
- Client Authentication: Client secret sent as post
- Client ID: KC2-IdP(与KC2的myRealm-myServer2领域中客户端名称一致)
- Client secret: *******(来自KC2的KC2-IdP客户端密钥)
- Advanced settings: Backchannel logout设为ON,其余为OFF;仅开启Do not store users,其余为OFF
3. KC2的myRealm-myServer2领域中KC2-IdP客户端配置
- Client ID: KC2-IdP
- Root URL: 空
- Home URL: 空
- Valid redirect URIs:
https://myserver1:45003/* - Valid post logout redirect URIs:
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/logout - Web origins: *
- Admin URL: 空
- Client authentication: ON
- Authentication flow: 启用Standard flow和Direct access grants
- Logout settings:
- Front channel logout: OFF
- Backchannel logout URL:
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/logout - Backchannel logout session required: ON
- Backchannel logout revoke offline sessions: ON
排查思路与建议
- 验证KC1 IdP的Logout URL有效性:确认KC2的登出端点是否正确,可直接调用
https://myserver2:45003/realms/myRealm-myServer2/protocol/openid-connect/logout测试是否正常响应,同时检查KC1是否能访问该端点(排除网络/SSL信任问题) - 检查KC1是否保留KC2会话关联信息:由于启用了
transient-users,需确认KC1是否存储了来自KC2的会话ID(brokerSessionId),没有该信息则无法触发向KC2的登出请求。可通过KC1的会话详情查看是否包含IdP会话关联数据 - 调整KC1的登出流程:检查KC1的代理登出流程是否包含「Identity Provider Logout」步骤,默认流程可能需要手动添加该步骤,确保登出时触发IdP的会话销毁
- 确认KC2客户端的backchannel权限:检查KC2的KC2-IdP客户端是否开启Backchannel logout,同时确保该客户端允许KC1的IP/域名发起请求,验证客户端认证(Client ID/Secret)是否能正常通过KC2的校验
- 针对性查看KC1 Broker日志:开启
org.keycloak.broker的TRACE级别日志,重点关注登出阶段的日志,查看是否有尝试调用KC2登出端点的记录,是否存在隐藏错误(如认证失败、SSL握手问题) - 检查应用登出请求参数:确认Spring Security发起的登出请求是否传递了
id_token_hint参数,KC1需要该参数来识别用户关联的IdP会话,进而触发跨IdP的登出 - 验证KC1与KC2的客户端认证一致性:再次核对KC1的IdP配置中的Client ID、Secret与KC2的客户端配置完全匹配,backchannel登出请求需要通过客户端认证才能被KC2接受
内容的提问来源于stack exchange,提问作者Andrei Jivan
相关产品推荐
相关产品推荐

