Repository navigation
feat(auth): return to DevLake after OIDC logout and show a login error page - #9351
Merged
Merged
Conversation
…r page RP-initiated logout: - /auth/logout now sends client_id, post_logout_redirect_uri and id_token_hint to the IdP's end_session_endpoint, so IdPs such as Keycloak >= 18 skip the logout prompt and return the user to DevLake. - The id_token is stored in auth_sessions (new column, migration 20261107000001) only when OIDC_LOGOUT_REDIRECT=true, and is cleared on revocation. - New OIDC_<NAME>_POST_LOGOUT_REDIRECT_URL; defaults to the origin of OIDC_<NAME>_REDIRECT_URL plus "/". Login error page: - Browser-facing failures in /auth/login and /auth/callback redirect to the new config-ui route /auth-error?code=<code> instead of returning raw JSON. Codes: forbidden, expired, idp_error, server_error. Details are only logged server-side. - For rejected users (OIDC_ALLOW_EMAILS/OIDC_ALLOW_DOMAINS) the page offers "Request access" (new OIDC_ACCESS_REQUEST_URL, exposed via /auth/methods) and "Sign in with a different account", which calls the new /auth/switch-account endpoint to end the IdP session using an encrypted, short-lived id_token hint cookie. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
klesh
approved these changes
Nov 9, 2026
klesh
left a comment
Contributor
There was a problem hiding this comment.
LGTM
Thanks for your contribution.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
env.example)pr-type/bug-fix,pr-type/feature-development, etc.(I can't set labels myself; suggested:
pr-type/feature-development,component/config-ui)Summary
Two gaps in the OIDC login added in #8854:
OIDC_LOGOUT_REDIRECT=true,/auth/logoutreturns the bareend_session_endpoint. Keycloak 18+ thenshows "Do you want to log out?" and leaves the user on a Keycloak page.
OIDC_ALLOW_DOMAINS/OIDC_ALLOW_EMAILSgets403 {"message":"user is not allowed"}in the browser. Their IdP session stays alive, so clicking"Sign in" again ends in the same error without a way out.
RP-initiated logout
logoutUrlnow carriesclient_id,post_logout_redirect_uriandid_token_hint(OpenID Connect RP-Initiated Logout 1.0). Keycloak skips theconfirmation prompt and sends the user back to DevLake.
OIDC_<NAME>_POST_LOGOUT_REDIRECT_URL. Default: origin ofOIDC_<NAME>_REDIRECT_URL+/.auth_sessions.id_tokencolumn (migration20261107000001). It is only stored whenOIDC_LOGOUT_REDIRECT=true,never exposed via JSON, and cleared when the session is revoked.
Login error page
/auth/loginand/auth/callbacknow redirectto a new config-ui route
/auth-error?code=<code>instead of returningJSON. Codes:
forbidden,expired(state/cookie problems),idp_error(IdP returned an error, discovery/exchange/verification failed),
server_error. Details only go to the server log; rejected logins are loggedas a warning with
subandemail.TipLayout(same look as the other error pages).forbidden:OIDC_ACCESS_REQUEST_URLis set (exposed via
/auth/methodsasaccessRequestUrl).GET /auth/switch-account, which ends the IdP session and returns toDevLake. The id_token for the hint is passed in a short-lived (10 min),
encrypted, HttpOnly cookie set during the rejected callback, since no
DevLake session exists for that user.
Does this close any open issues?
N/A (follow-up to #8854)
Screenshots
Rejected user (
forbidden, withOIDC_ACCESS_REQUEST_URLset):Expired or tampered state (
expired):Other Information
Upgrade note: deployments that already run with
OIDC_LOGOUT_REDIRECT=truenow send
post_logout_redirect_uriby default. It must be registered at theIdP (Keycloak: Valid post logout redirect URIs; Entra ID: add it as a
redirect URI of the app registration). Otherwise the IdP rejects the logout request.
Known limits
becomes unreachable later,
/auth/loginstill redirects to it and thebrowser shows its own error; DevLake cannot catch that.
very large id_tokens (many group claims). The browser then drops it and the
logout falls back to no
id_token_hint, so the IdP shows its confirmationprompt.
/auth-error,/), like the existingpost-login redirect.
Testing
go test ./server/api/... ./helpers/oidchelper/ ./core/models/migrationscripts/...(backend) and
npx vitest run(config-ui, newauth-error.test.tsx) — passed.golangci-lint runon the changed packages andmake migration-script-lint— passed.
rejected domains), PostgreSQL 18.6, backend + Vite dev proxy: login,
logout without prompt and return to DevLake, IdP session ended,
forbiddenpage with both buttons, switch account,
expired/idp_error/server_errorpages,
OIDC_LOGOUT_REDIRECT=false(no id_token stored) — all as expected.PostgreSQL, config-ui, license header, Grafana check):
https://github.com/DoDiODev/devlake/actions/runs/42589488952 (16/16 jobs green)