PAC4J在 RP发起的登出过程中不提供id_token_hint

编程语言 2026-07-09

运行位于 https://github.com/pac4j/play-pac4j-scala-demo/ 的PAC4J Play演示应用时,我发现 集中登出 功能在与(较新版本的)Keycloak搭配使用时不起作用,Keycloak要求在RP发起的登出场景中必须携带 id_token_hint 参数。

调试代码流程时,我理解在将 OidcProfile 对象保存到会话存储时,身份令牌信息会丢失。
特别是由于提交 https://github.com/pac4j/pac4j/commit/a32dfca7012f924ef3eb23f920a3e8d298393c0a:

// pac4j-oidc/src/main/java/org/pac4j/oidc/profile/OidcProfile.java
   @Override
    public void removeLoginData() {
        removeAttribute(OidcProfileDefinition.ID_TOKEN);
        removeAttribute(OidcProfileDefinition.ACCESS_TOKEN);
        removeAttribute(OidcProfileDefinition.REFRESH_TOKEN);
    }

有哪些推荐的解决方案?
我是不是应该扩展 OidcProfile 类并实现一个不会清除身份令牌的自定义实现?

不过从安全方面看会有什么后果?把身份令牌/访问令牌/刷新令牌保存在会话存储中(即作为cookie)究竟有什么问题?毕竟cookie是用服务器端只有服务器知道的密钥来进行加密的。

解决方案

确实,当你使用 PlayCookieSessionStore 时,你的用户资料会被保存到Play的 cookie中。

这本身并没有安全问题。问题在于cookie的大小有限,这也是在保存到 OidcProfile 之前会移除较大信息的原因。否则,cookie无法写入,用户资料也就无法保存。

但你说得对,这对于集中登出来说是一个问题,需要发送参数 id_token_hint

一个解决方案是使用另一种存储,例如 PlayCacheSessionStorePlayEhCacheSessionStore

另一种解决方案是更新 PlayCookieSessionStore,添加一个标志来指示是否调用 clearUserProfiles 方法,但它要么移除所有令牌,要么不移除。我不确定在不移除任何令牌的情况下是否真的可行。

或者你的提议是正确的:覆盖 profileDefinition 来创建一个不移除id_token的自定义 OidcProfile

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章