Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keycloak Backchannel logout

I was trying to understand the flow of a backchannel logout from my web application, but I find the documentation confusing. I have a JEE application running in JBoss EAP, with a Java Servlet Filter Adapter (for some technical reasons, I can't use the EAP adapter). The documentation for logging out says:

You can log out of a web application in multiple ways. For Java EE servlet containers, you can call HttpServletRequest.logout(). For other browser applications, you can redirect the browser to http://auth-server/auth/realms/{realm-name}/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri, which logs you out if you have an SSO session with your browser.

The documentation for the Admin URL configuration says:

For example the way backchannel logout works is: 1. User sends logout request from one application 2. The application sends logout request to Keycloak 3. The Keycloak server invalidates the user session 4. The Keycloak server then sends a backchannel request to application with an admin url that are associated with the session 5. When an application receives the logout request it invalidates the corresponding HTTP session

So from my understanding, either:

  1. calling HttpServletRequest.logout() is supposed to send a request to Keycloak
  2. a GET to http://auth-server/auth/realms/{realm-name}/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri should somehow detect the clientId (from the redirect URI?) and send a request to the appropriate backchannel

Neither option seems to work for me. In neither case, do I get a callback from Keycloak to my adminUrl. Furthermore, I still see the same number of active sessions in my Keycloak Admin after calling Request.logout(). According to this SO post, it seems to work, but I'm not sure if I am missing a configuration or something of the sorts.

I've tried sending the GET to the logout endpoint with an access_token, but that doesn't make any difference either.

What am I misunderstanding from this documentation? How am I supposed to code the logout?

like image 208
Eric B. Avatar asked May 02 '18 20:05

Eric B.


1 Answers

The ordinary logout and the backchannel logout are two complete different things.

The ordinary logout works by redirecting the browser to the URL you mentioned in (2). The user is recognized by the browser session in Keycloak, hence a browser redirect is crucial (the redirect_uri is not even necessary to provide).

We achieved this in Tomcat by calling the following code in our application which triggers the redirect by itself (using the keycloak.json as configuration, of course):

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 necessary (???)

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

A backchannel logout makes only sense if there are several relying parties (in OIDC speak) or "clients" in terms of Keycloak in play. It ensures that no client sessions of clients in the same realm (for the same user) "survive" the logout.

After performing the logout above, Keycloak checks if there are client sessions associated with the Keycloak session and sends backchannel logout requests to the corresponding clients (in the same realm!), hence a browser session is not involved in this process at all.

To make this work (for both Node.js and Tomcat with the corresponding Keycloak adapter properly installed) it was only necessary for us to configure the Admin URL of the clients in Keycloak properly. Note: It defaults to "/", but for Tomcat the webapp context must be included, e.g. https://myapp.com/mywebapp/

like image 182
Simon Avatar answered Sep 18 '22 15:09

Simon