Removing Keycloak session after SAML Logout

I have an issue when trying to log a user out from a session that was created by logging in through a SAML identity provider.

I am using Keycloak v6.0.2 and the Keycloak node JS adapter. The situation is as follows (assuming we have a logged in user with a Keycloak session):

  1. User’s browser is directed to the logout endpoint of the node JS adapter.
  2. This endpoint redirects the browser to the Keycloak logout endpoint: https://<keycloak_host>/auth/realms/317/protocol/openid-connect/logout
  3. Keycloak redirects the browser to the SAML logout endpoint of the identity provider. At this point the redirect path stops and the browser displays the message: “You have been logged out” (it is a Microsoft ADFS system).

The problem is that the user session in Keycloak still exists at this point (visible by finding the user through the administration interface and then looking at her sessions). This means that when the user returns to the application, she is just logged in again, and this will be the case until the Keycloak session expires. What surprises me is that in step 2 of the flow described above, Keycloak does not destroy the user session. Why is this? Is Keycloak expecting the identity provider to redirect the user back to Keycloak before removing the session?

At the moment the only solution to this issue seems to be that my application must do 2 things to ensure logout is complete:

  1. It must redirect the browser to Keycloak so that Keycloak can redirect to the external identity provider in order for logout to occur there
  2. It must make a REST API call to the Keycloak server to destroy the user session, given that this does not occur during step 1.

Has anyone else encountered this scenario? Are there any other possible solutions?

2 Likes

Hi @evansnicholas,
Have you figured out any alternative solutions?
I have the exact same problem currently, and I would love to hear any insight you might have!

The same issue on my side :(.
Also keycloak has “backchannel logout” options for IDP. In this case your application will stay on keycloak page and keycloak session will be destroyed but IDP will be notified about logout via server-to-server call.

We are also experiencing this same problem and looking for a solution.

In our case, if user is not logged into any other client through the same IDP, logout works as intended. But if user has logged into two or more clients through same IDP and logs out from any of our clients protected by Keycloak, they are logged out from every other client but not from the one that initiated the single logout. Note that our IDP doesn’t support backchannel logout.

We have set logging level to debug and had following results:

First we logged in with clientOne and used SSO to log into clientTwo. After that we logged out with clientOne and got following log messages:
2020-04-20 10:28:11,809 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-569) backchannel logout to: clientOne
2020-04-20 10:28:11,810 DEBUG [org.keycloak.services.managers.ResourceAdminManager] (default task-569) Cant logout {0}: no logged adapter sessions
2020-04-20 10:28:11,825 DEBUG [org.keycloak.protocol.oidc.endpoints.LogoutEndpoint] (default task-569) finishing OIDC browser logout

After that, keycloak gets SAML Logout Request from IDP that is used to initiate logout for clientTwo that is in separate realm from clientOne. It gives following log messages:
2020-04-20 10:28:16,601 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-568) backchannel logout to: clientTwo
2020-04-20 10:28:16,601 DEBUG [org.keycloak.services.managers.ResourceAdminManager] (default task-568) Cant logout {0}: no logged adapter sessions
2020-04-20 10:28:16,601 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-568) All clients have been logged out for user

And after this, we test to browse to clientOne and clientTwo. clientOne still has keycloak session active, while clientTwo forwards to authenticate with IDP.

We have been investigating our case and seems that our IDP is for some reason unable to send SAML LogoutResponse to client that initiated SLO. I assume that keycloak logs SLO initiating client out only after getting that response from IDP.

I created a bug https://issues.redhat.com/browse/KEYCLOAK-13686

Hi @mkopeyka, similar issue here…
This ticket was deleted? :confused:
I can’t find/see it…
thanks

Ticket still alive. Probably you have to login into redhat account to see it.

Ticket is not visible to me either, even after logging in with redhat account. It says that either ticket was deleted or I don’t have permissions to view it.

For microsoft federated domains I managed to resolve this issue using https://<keycloak_host>/auth/realms/<realm_name>/protocol/saml as -LogOffUri

Yes, I think this is similar to my solution. I have to explicitly destroy the keycloak session by making this API call. It is not very elegant however because you don’t want to destroy the session before Keycloak has had the chance to redirect to the user to the federated domain so logout can happen there as well. In order to prevent this I delay destroying the keycloak session for a few seconds after redirecting.

My ticket has been closed with this resolution

This is a SAML flow violation and nothing can be done on Keycloak side. LogoutResponse is mandatory per the specification, and unless received, the session cannot be marked as logged out.
See https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf, lines 2570-2571

Hi, I am eager to know how to configure backchannel logout on keycloak. I am using keycloak 10.0.2 as SAML IDP. And i am struggling to find a way to logout without refreshing (redirect) browser.It would be much appreciated, if you can help with some details or relative documents. Thanks a lot !

Hi @archerbj ,

Backchannel logout is standard option of IDP in Keycloak.

@mkopeyka
Thanks for your reply. Referring to SAML specification, only SOAP binding supports back channel communication. Do you mean the SOAP binding is standard option ? Or can i just call a REST api and wait for the completion of the whole logout process?

BTW,My server is a nodeJS server and i am not using a keycloak client but a typical saml client, is there any difference between that ?