Keycloak Backchannel注销

时间:2018-05-02 20:48:51

标签: java-ee keycloak

我试图从我的Web应用程序中了解反向通道注销的流程,但我发现文档令人困惑。我有一个在JBoss EAP中运行的JEE应用程序,Java Servlet Filter Adapter(由于某些技术原因,我不能使用EAP适配器)。 documentation for logging out说:

  

您可以通过多种方式注销Web应用程序。对于Java EE   servlet容器,可以调用HttpServletRequest.logout()。对于   其他浏览器应用程序,您可以将浏览器重定向到   http://auth-server/auth/realms/ {realm-name} / protocol / openid-connect / logout?redirect_uri = encodedRedirectUri,如果您与浏览器进行SSO会话,则会将您注销。

Admin URL configuration的文档说:

  

例如,backchannel注销的工作方式是:   1.用户从一个应用程序发送注销请求   2.应用程序向Keycloak发送注销请求   3. Keycloak服务器使用户会话无效   4.然后,Keycloak服务器向应用程序发送一个反向通道请求,其中包含与该会话关联的管理URL   5.当应用程序收到注销请求时,它会使相应的HTTP会话无效

根据我的理解,要么:

  1. 调用HttpServletRequest.logout()应该向Keycloak发送请求
  2. GET到http://auth-server/auth/realms/{realm-name}/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri应该以某种方式检测clientId(来自重定向URI?)并向适当的反向通道发送请求
  3. 这两种选择似乎对我都不起作用。在这两种情况下,我都没有从Keycloak回复到我的adminUrl。此外,在调用Request.logout()之后,我仍然在我的Keycloak Admin中看到相同数量的活动会话。根据{{​​3}},它似乎有效,但我不确定我是否缺少配置或类似的东西。

    我尝试使用access_token将GET发送到注销终端,但这也没有任何区别。

    我从这份文件中误解了什么?我该如何编写注销代码?

2 个答案:

答案 0 :(得分:3)

普通注销和反向通道注销是两个完全不同的东西。

普通注销的工作原理是将浏览器重定向到您在(2)中提到的网址。用户被Keycloak中的浏览器会话识别,因此浏览器重定向至关重要(甚至不需要提供redirect_uri)。

我们在Tomcat中通过调用我们的应用程序中的以下代码实现了这一点,该代码自动触发重定向(当然,使用keycloak.json作为配置):

Object keycloakAttr = request.getAttribute(KeycloakSecurityContext.class.getName());
if (keycloakAttr != null && keycloakAttr instanceof RefreshableKeycloakSecurityContext) 
{
  // code inspired by org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.logoutInternal
  RefreshableKeycloakSecurityContext ksc = (RefreshableKeycloakSecurityContext)keycloakAttr;
  KeycloakDeployment deployment = ksc.getDeployment();
  ksc.logout(deployment);

  // Since a CatalinaSessionTokenStore is used as token store in Tomcat
  // tokenStore.logout() is not be necessary (???)

  request.removeAttribute(KeycloakSecurityContext.class.getName());
  request.setUserPrincipal(null);
}

反向频道注销仅在多个依赖方(在OIDC发言中)或“客户”中的Keycloak方面才有意义。它确保同一领域(针对同一用户)的客户端的客户端会话不会在注销中“存活”。

执行上面的注销后,Keycloak会检查是否存在与Keycloak会话关联的客户端会话,并将反向通道注销请求发送到相应的客户端(在同一个域中!),因此浏览器会话根本不涉及此过程

为了使这项工作(对于Node.js和Tomcat都正确安装了相应的Keycloak适配器),我们只需要正确配置Keycloak中客户端的管理URL。注意:它默认为“/”,但对于Tomcat,必须包含webapp上下文,例如https://myapp.com/mywebapp/

答案 1 :(得分:0)

您不使用Keycloak的适配器之一吗?我遇到了完全相同的问题。

事实证明,当密钥交换交换代码时,自己的密钥斗篷适配器将if (exception is MongoBulkWriteException<T> mostRecentException) { var unProcessedRequests = mostRecentException.UnprocessedRequests.ToList(); if (mostRecentException.WriteErrors.Any()) { //get processed requests (without success) that failed and add to remainingWork var requestWithError = new[] { mostRecentException.Result.ProcessedRequests[ mostRecentException.WriteErrors[0].Index] }; unProcessedRequests = unProcessedRequests.Concat(requestWithError).ToList(); } remainingWork = unProcessedRequests.ToList(); } else if (exception is CosmosDbRateLimitingBugException<T> cosmosDbBug) { remainingWork = cosmosDbBug.UnprocessedRequests; } 的POST发送到client_session_state

除非在protocol/openid-connect/token POST中提供了这样的参数,否则不会调用AdminURL。去搞清楚。添加该参数,它将开始工作!

查看相关的keycloak forum post