Skip to content

feat(oidc): implement RP-Initiated Logout - #1829

Open
stevecharon wants to merge 1 commit into
DependencyTrack:mainfrom
stevecharon:feat/oidc-rp-initiated-logout
Open

stevecharon wants to merge 1 commit into
DependencyTrack:mainfrom
stevecharon:feat/oidc-rp-initiated-logout

Conversation

@stevecharon

Copy link
Copy Markdown

Perform an RP-Initiated Logout as specified in OpenID Connect RP-Initiated Logout 1.0 when, and only when, the current session was established via OIDC. Sessions of managed and LDAP users are unaffected and keep the previous local-only behavior.

The API server does not expose the principal type via /api/v1/user/self, and the OIDC user is intentionally removed from the web storage right after the token exchange. The login view therefore records the ID token in the session storage, which the logout handler consumes as id_token_hint and clears.

The UserManager, previously constructed inline in the login view, moves to src/shared/oidc.js so it can be shared. The end session endpoint is taken from the provider's discovery document, so no additional configuration is required.

Description

Implements OpenID Connect RP-Initiated Logout.

When a user authenticated via OIDC logs out, the frontend only drops the local
session token and redirects to the login view. The session at the identity
provider stays active, so clicking the OpenID button logs the user straight
back in without presenting any credentials.

Logging out now terminates the session at the identity provider as well, but
only for sessions that were actually established via OIDC. Managed and LDAP
users keep the previous local-only behavior, so this is not a breaking change
and requires no new configuration.

Addressed Issue

Fixes DependencyTrack/dependency-track#2015

Additional Details

Determining at logout time whether the current session came from OIDC is not
straightforward:

  • /api/v1/user/self does not expose the principal type. Managed users can be
    identified by the presence of suspended, but LDAP users are
    indistinguishable from OIDC users that way.
  • oidcUserManager.getUser() returns null, because Login.vue removes the
    OIDC user right after exchanging the access token for a session token.

Login.vue therefore records the ID token in sessionStorage at the point
where the token exchange provably succeeded. The logout handler consumes it as
id_token_hint and clears it. This tracks how the current session was
established
rather than the account type, which is the more accurate
condition — a user who happens to have an OIDC account but signed in some
other way should not trigger an IdP logout either.

The UserManager was previously constructed inline in Login.vue and thus
unreachable from the header component. It moves to src/shared/oidc.js as a
lazily created singleton that returns null when OIDC is not configured, so
callers can fall back to the local redirect.

Notes:

  • No new dependency. oidc-client 1.11.5 is already in use and ships
    signoutRedirect().
  • No new configuration. end_session_endpoint comes from the provider's
    discovery document; post_logout_redirect_uri defaults to the frontend
    origin including the context path.
  • If the redirect fails, the handler falls back to the local login redirect.

Verified against Keycloak using the code flow: after logging out, clicking the
OpenID button again presents the Keycloak login form instead of silently
re-authenticating.

Operators need to register the frontend origin as a post-logout redirect URI
at their IdP. Happy to open a corresponding PR against the docs repo.

Checklist

When a user authenticated via OIDC logs out, the frontend only dropped the
local session token and redirected to the login view. The session at the
identity provider remained active, so clicking the OpenID button logged the
user straight back in without presenting any credentials.

Perform an RP-Initiated Logout as specified in OpenID Connect RP-Initiated
Logout 1.0 when, and only when, the current session was established via OIDC.
Sessions of managed and LDAP users are unaffected and keep the previous
local-only behavior.

The API server does not expose the principal type via /api/v1/user/self, and
the OIDC user is intentionally removed from the web storage right after the
token exchange. The login view therefore records the ID token in the session
storage, which the logout handler consumes as id_token_hint and clears.

The UserManager, previously constructed inline in the login view, moves to
src/shared/oidc.js so it can be shared. The end session endpoint is taken
from the provider's discovery document, so no additional configuration is
required.

Fixes DependencyTrack/dependency-track#2015

Signed-off-by: stevecharon <37655537+stevecharon@users.noreply.github.com>
@owasp-dt-bot

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

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.

Logout of OIDC session shall implement OIDC logout

2 participants