Skip to content

auth-oauth2: Add optional OIDC RP-Initiated Logout support#302

Open
dhm-msd wants to merge 1 commit into
osTicket:developfrom
dhm-msd:feature/auth-oauth2-oidc-rp-initiated-logout
Open

auth-oauth2: Add optional OIDC RP-Initiated Logout support#302
dhm-msd wants to merge 1 commit into
osTicket:developfrom
dhm-msd:feature/auth-oauth2-oidc-rp-initiated-logout

Conversation

@dhm-msd
Copy link
Copy Markdown

@dhm-msd dhm-msd commented Apr 23, 2026

Summary

The auth-oauth2 plugin currently only clears the local PHP session on
logout. For OIDC providers (e.g. Keycloak, Okta), the IdP session stays
alive — clicking login again silently re-authenticates the user without
any credential prompt.

This PR implements RP-Initiated Logout (OIDC spec §5):
after clearing the local session, the plugin redirects the browser to the
IdP's end_session_endpoint with id_token_hint, client_id, and
post_logout_redirect_uri. The IdP terminates its own session and
redirects the user back to osTicket.

Changes

config.php

  • Added getLogoutUrl() and getPostLogoutRedirectUri() getters to OAuth2Config
  • Added two optional fields to the plugin instance config UI (hidden for authorization-type instances):
    • Logout Endpoint (urlLogout) — the IdP's end_session_endpoint
    • Post-Logout Redirect URI (urlPostLogout) — where to land after IdP logout; defaults to the osTicket base URL

oauth2.php

  • Added Token::getIdToken() — extracts the OIDC id_token from the token response (stored automatically by the League OAuth2 client in getValues())
  • Updated OAuth2AuthenticationTrait::callback() — saves id_token, logout_url, post_logout_uri, and client_id into the existing $_SESSION[':oauth'][{id}] session namespace at login time
  • Updated OAuth2AuthenticationTrait::signOut() — reads those values, calls parent::signOut() to clear the local session, then redirects to the IdP logout URL if one is configured

Backward compatibility

The feature is opt-in: when urlLogout is left blank (the default for
all existing instances), signOut() behaves identically to before — only
the local session is cleared, no redirect occurs.

Configuration (Keycloak example)

In the plugin instance settings, set:

  • Logout Endpoint: https://{keycloak-host}/realms/{realm}/protocol/openid-connect/logout
  • Post-Logout Redirect URI: https://{osticket-host}/ (must be registered as a valid post-logout redirect URI in the IdP client)

Scopes must include openid so the IdP issues an id_token alongside the access token.

Store the id_token, end_session_endpoint URL, client_id, and
post_logout_redirect_uri in the OAuth session at login time. On logout,
redirect the browser to the IdP's end_session_endpoint so the IdP
session is also terminated.

Feature is opt-in via two new optional fields on the plugin instance
config (Logout Endpoint, Post-Logout Redirect URI). When blank, signOut
behaves identically to before — only the local PHP session is cleared.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant