8000 Logout authentication session handling deletes shared roots, reuses tabs across sessions, and leaves auth session hash stale · Issue #55118 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content

Logout authentication session handling deletes shared roots, reuses tabs across sessions, and leaves auth session hash stale #55118

Description

@shawkins

Before reporting an issue

  • I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.

Area

authentication

Describe the bug

Following the changes in #54942 (session takeover fix for logout auth sessions), three related edge cases in logout authentication session lifecycle and cookie synchronization remain open:

  1. backchannelLogout deletes shared root authentication session containing unrelated login tabs (PR review r4517402901): AuthenticationManager.backchannelLogout removes the entire root authentication session in its finally block assuming the root is dedicated to the logout. When the logout session is created in or joined to a shared root (e.g., matching AUTH_SESSION_ID cookie or matching user session ID), unrelated in-progress login tabs in that root are deleted, forcing users to restart their login.

  2. Logout auth session in a shared root is reused across different user sessions without clearing per-client logout states (PR review r4517402976): AuthenticationManager.createOrJoinLogoutSession looks up any existing tab with action LOGGING_OUT in the root and reuses it without verifying that the LOGOUT_USER_SESSION_ID auth note matches the user session being logged out. Stale per-client logout markers (LOGGED_OUT, LOGGING_OUT set by setClientLogoutAction) from an earlier, unfinished logout of a different user session are retained, which can suppress logout notifications to downstream clients of the new user session.

  3. Stale KC_AUTH_SESSION_HASH cookie when creating a new logout root (PR review r4540170938): AuthenticationManager.bindLogoutRootToBrowser updates the AUTH_SESSION_ID cookie when creating a new random logout root, but does not update KC_AUTH_SESSION_HASH. The hash cookie can retain the hash of the prior root for up to 60 seconds. If an abandoned logout confirmation is followed by a prompt=login request joining that root, authChecker.js encounters a hash mismatch and repeatedly reloads the login form until the hash cookie expires.

Version

main (999.0.0-SNAPSHOT)

Regression

  • The issue is a regression

Expected behavior

  1. backchannelLogout should only remove the logout authentication session tab, and delete the root authentication session only when no other tabs remain (or only if the root was created specifically for that logout).
  2. createOrJoinLogoutSession should verify LOGOUT_USER_SESSION_ID before reusing an existing LOGGING_OUT tab in the root; if the user session differs, it should remove the old tab and create a fresh one without stale client states.
  3. bindLogoutRootToBrowser should synchronize the KC_AUTH_SESSION_HASH cookie alongside AUTH_SESSION_ID whenever a new logout root is bound to the browser.

Actual behavior

  1. Unrelated login tabs in the shared root are deleted during backchannel logout.
  2. An existing logout session tab is reused across user sessions, retaining stale per-client logout states that may suppress downstream client logout notifications.
  3. KC_AUTH_SESSION_HASH is left stale when a new logout root is assigned, causing repeated client-side login form reloads in authChecker.js.

How to Reproduce?

Item 1 (Shared root deletion):

  1. Open a login page in a browser to create an in-progress login tab in root R with an AUTH_SESSION_ID cookie for R (and no identity cookie).
  2. Open /protocol/openid-connect/logout?id_token_hint=<valid id token of another user session> in the same browser.
  3. The fallback backchannel logout runs and deletes root R, destroying the login tab from step 1.

Item 2 (Cross-session logout tab reuse):

  1. Start a logout for user session A that does not complete (e.g. abandoned confirmation screen).
  2. In the same browser/root, initiate a logout for user session B.
  3. createOrJoinLogoutSession reuses A's logout session for B with A's client logout states intact.

Item 3 (Stale hash cookie reload loop):

  1. Log in, then trigger a logout flow that creates a new random logout root and updates AUTH_SESSION_ID (without updating KC_AUTH_SESSION_HASH).
  2. Abandon the logout confirmation and initiate a new login with prompt=login within 60 seconds.
  3. authChecker.js detects a hash mismatch with KC_AUTH_SESSION_HASH and repeatedly reloads the page.

Anything else?

Spotted during code review of PR #54942:

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/authenticationAuth flows, authenticators, required actions, OTP, password policies, brute forcekind/bugCategorizes a PR related to a bugstatus/triageteam/core-authn

    Type

    Fields

    No fields configured for bug.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    0