keycloak / keycloak

Open Source Identity and Access Management For Modern Applications and Services
https://www.keycloak.org
Apache License 2.0
22.31k stars 6.61k forks source link

User logout -> clients receive ambiguous backchannel logout token #22914

Open duckboy81 opened 1 year ago

duckboy81 commented 1 year ago

Before reporting an issue

Area

authentication

Describe the bug

When a client enables Backchannel logout session required and a user is logged out of all sessions via the logout endpoint (/admin/realms/{realm}/users/{user_id}/logout), the client is not notified to end ALL sessions, just the first session keycloak reaches.

There is no difference between the request sent by Keycloak to a client for A) a single session logout or B) an entire user logout (i.e. logout all sessions)

PS: The reverse is true if Backchannel logout session required is NOT enabled. The logout token sent to a client looks like a request to logout every session although an admin may only want to logout of a particular session.

Version

22.0.1

Expected behavior

The expected behavior can be one of two options:

  1. A client received a logout token sid claim removed

    If a sid Claim is not present, the intent is that all sessions at the RP for the End-User identified by the iss and sub Claims be logged out https://openid.net/specs/openid-connect-backchannel-1_0.html

  2. Keycloak sends a logout request for each session, even if it means sending more than one request per client


Sample JWT for option 1

eyJhbGciOiJQUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJnTkFjd1d5M3o3SlpVdnJGaVI5Z3pqemhldlJBVlNSdFJ1NmN2ZXlxSzB3In0.eyJpYXQiOjE2OTM3NDk3NzMsImp0aSI6ImY1OWNjZTg4LWQ2YjctNDU0ZS1iNzRkLWUwMjI0MGMxMTMxZSIsImlzcyI6Imh0dHA
6Ly9sb2NhbGhvc3Q6ODA4MC9yZWFsbXMvbG9jYWwtZGV2IiwiYXVkIjoidGhlLWR1bXAiLCJzdWIiOiJjNDNkN2EzOC03NDUyLTQ2MmMtYjRhNy0zNGQ5MjY1YjAzMzYiLCJ0eXAiOiJMb2dvdXQiLCJldmVudHMiOnsiaHR0cDovL3NjaGVtYXMub3BlbmlkLm5ldC9ldmVudC9iYWNrY2hhbm5lbC1sb2dvd
XQiOnt9LCJyZXZva2Vfb2ZmbGluZV9hY2Nlc3MiOnRydWV9fQ.fA7GOtV8zam1IS-IYgxHg7byYwqlaJGk51cmTgrbHMmrqBCRUJAGFwU2_d2jaKbYeeorTxGapyuYYWo6tis-8CIRVNbBCUVH0WsG3FL9glitCcGdxjqgNj_4CV5YRl2U-nLxEaGzN4fqH7idtoFuVS5IrFdtA2uF73TrLZUKdJycyDPQXQBc
k0tlqL45Zp1cHeoNWpbVUr2yrC29vFGaAMGayooQeji3044OotnPp7SU2FXAzRKVQVj7IG40-y2lOMnQeij_iO5YXFWIiJANR0nUkSlFGzZg-0wdvNOpE3WVDrYdjWqDw_Uvj9qmC3PHjwVXOTYs57dEVjKxu31TBg

...associated payload

{
  "iat": 1693749773,
  "jti": "f59cce88-d6b7-454e-b74d-e02240c1131e",
  "iss": "http://localhost:8080/realms/local-dev",
  "aud": "the-dump",
  "sub": "c43d7a38-7452-462c-b4a7-34d9265b0336",
  "typ": "Logout",
  "events": {
    "http://schemas.openid.net/event/backchannel-logout": {},
    "revoke_offline_access": true
  }
}

Actual behavior

Keycloak only sends one logout request per client, regardless of the number of active sessions a client may have for the user. The token in this request regretfully includes the sid claim, telling the client to only logout that particular session (and not all the user's sessions as intended).


Example logout token (where user has 2 active sessions in this client)

eyJhbGciOiJQUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJnTkFjd1d5M3o3SlpVdnJGaVI5Z3pqemhldlJBVlNSdFJ1NmN2ZXlxSzB3In0.eyJpYXQiOjE2OTM3NDIzNTUsImp0aSI6IjA4MTI5YmE1LTk2ZmMtNDAxMC04MzVkLTI0NTVhOGExZmM3NSIsImlzcyI6Imh0dHA
6Ly9sb2NhbGhvc3Q6ODA4MC9yZWFsbXMvbG9jYWwtZGV2IiwiYXVkIjoidGhlLWR1bXAiLCJzdWIiOiJjNDNkN2EzOC03NDUyLTQ2MmMtYjRhNy0zNGQ5MjY1YjAzMzYiLCJ0eXAiOiJMb2dvdXQiLCJzaWQiOiI5M2QwNzRmYi0yNTY1LTQ4MGUtOGIxNy0zMTAxOTk2ZGNkOTEiLCJldmVudHMiOnsiaHR0c
DovL3NjaGVtYXMub3BlbmlkLm5ldC9ldmVudC9iYWNrY2hhbm5lbC1sb2dvdXQiOnt9LCJyZXZva2Vfb2ZmbGluZV9hY2Nlc3MiOnRydWV9fQ.BjSz6PPG_TO2VUuBt6MOl5PSgyM6AnIw4K0R7HKjWBeG2Yi70O1m6d0VSTEeORYWfMku2oKG94E6teFfNRDDUgKjSLEjWhnJOqgVUv3VLXdcxMsnvPStNDcp
fNUlx5wDAFeDIxq3pOvjec7gNeXK8fU0iPCakH_quTeEowJSAX1eTe78tT1-Oj-fqRrlkG2Hyp799WXuEGaa8_xqqIBQ-4RtwmnzxQB8aZEJAHyuu-QikongY6aI-huVb4LOqEAH2Jg6BKGIGi2qY_fg1oHxcage8VtwN3bLDeWS_81JdD2NCLSc_OwuYCpy6jYePJs2NEvRwczlJiwWClju23lEgg

...associated payload

{
  "iat": 1693742355,
  "jti": "08129ba5-96fc-4010-835d-2455a8a1fc75",
  "iss": "http://localhost:8080/realms/local-dev",
  "aud": "the-dump",
  "sub": "c43d7a38-7452-462c-b4a7-34d9265b0336",
  "typ": "Logout",
  "sid": "93d074fb-2565-480e-8b17-3101996dcd91",
  "events": {
    "http://schemas.openid.net/event/backchannel-logout": {},
    "revoke_offline_access": true
  }
}

How to Reproduce?

Client Setup:

Steps:

  1. Log in twice to the same client using the same credentials
  2. Access the active user sessions page in the admin console and select "Logout all sessions"
  3. Observe the single request sent to the client from Keycloak

Result: Observed request sent to client is to logout a specific session, not all sessions.

Anything else?

Section 2.4. Logout Token https://openid.net/specs/openid-connect-backchannel-1_0.html

A Logout Token MUST contain either a sub or a sid Claim, and MAY contain both. If a sid Claim is not present, the intent is that all sessions at the RP for the End-User identified by the iss and sub Claims be logged out.

duckboy81 commented 1 year ago

Off the top, one counter argument to my PR could be that where a client has Backchannel logout session required enabled, my implementation would essentially go against this. See option 2 in my PR for a different, more costly approach.

pedroigor commented 10 months ago

I'm not sure if we have considered how to handle the Backchannel logout session required when logging out all user sessions. For me, it makes sense to avoid sending multiple logout requests to a client when there are multiple user sessions. We can send a single one without sid even though you have the Backchannel logout session required enabled.

Your PR is not yet preventing multiple logout requests to the same client. We probably want to avoid using a user session note but just set a session attribute or change how we call those methods when logging out all sessions.

buehner10 commented 2 months ago

We have the same issue and are in favor of the solution described in the OpenID spec. "A Logout Token MUST contain either a sub or a sid Claim, and MAY contain both. If a sid Claim is not present, the intent is that all sessions at the RP for the End-User identified by the iss and sub Claims be logged out."

Is there a plan for when the issue will be resolved?

tnishada commented 4 weeks ago

I am also having the same issue. When the user updates the password, he can choose the option to sign out from other devices. In that case relying party (RP) has to remove all the sessions except the newly created one (newly created when changing the password).

Therefore I think it is better to include all the removed session ids as an array in the logout token rather than sending a token without session ids.