Sign out without a confirmation prompt - #4455
Conversation
Drop the unconditional confirmation prompt from the Default Sign Out Flow so signing out completes on the first flow execution, and stop sending id_token_hint from the console so no signed token carrying identity claims lands in the sign-out URL. Read the logout parameters from r.Form rather than the query string. On a POST to the end_session_endpoint the parameters arrive in the form body, so the query string carried none of them and the sign-out flow received an empty parameter set. Add a sign-out flow template that terminates the session with no confirmation step, mirroring the new default.
📝 WalkthroughWalkthroughThe default sign-out flow now bypasses the confirmation prompt and calls session sign-out directly. A new console template applies the same direct behavior. The OAuth logout handler forwards form-body parameters alongside query parameters. The ThunderID SDK config disables ID token transmission during logout by default. ChangesDirect sign-out flow, logout form handling, and ID token config
Estimated code review effort: 2 (Simple) | ~12 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant LogoutHandler
participant SignOutFlow
Client->>LogoutHandler: POST /logout (form body with state)
LogoutHandler->>LogoutHandler: ParseForm merges r.Form
LogoutHandler->>SignOutFlow: forward sanitized parameters (state)
SignOutFlow-->>Client: redirect response
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
frontend/apps/console/src/hocs/__tests__/withConfig.test.tsxESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox. frontend/apps/console/src/hocs/withConfig.tsxESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/cmd/server/bootstrap/01-default-resources.yaml`:
- Around line 578-593: The sign-out flow and OAuth logout behavior require
documentation updates. In the relevant sign-out guide under
docs/content/guides/, document immediate default sign-out, the Silent Sign Out
template, and Conditional Confirmation behavior; in docs/content/apis.mdx,
document form-encoded POST support for the logout endpoint and its accepted
parameters. The YAML, templates.json, and handler.go sites require no direct
code changes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: cf6c8a80-a2d6-4ecf-bedc-5c2d3c371825
📒 Files selected for processing (6)
backend/cmd/server/bootstrap/01-default-resources.yamlbackend/internal/oauth/oauth2/logout/handler.gobackend/internal/oauth/oauth2/logout/handler_test.gofrontend/apps/console/src/features/flows/data/templates.jsonfrontend/apps/console/src/hocs/__tests__/withConfig.test.tsxfrontend/apps/console/src/hocs/withConfig.tsx
| onSuccess: session_signout | ||
| layout: | ||
| size: | ||
| width: 101 | ||
| height: 34 | ||
| position: | ||
| x: 62 | ||
| y: 278 | ||
| - id: prompt_confirm | ||
| type: PROMPT | ||
| layout: | ||
| size: | ||
| width: 350 | ||
| height: 300 | ||
| position: | ||
| x: 463 | ||
| y: 150 | ||
| meta: | ||
| components: | ||
| - type: TEXT | ||
| id: text_signout_title | ||
| label: '{{ t(signout:forms.confirm.title) }}' | ||
| variant: HEADING_1 | ||
| - type: TEXT | ||
| id: text_signout_desc | ||
| label: '{{ t(signout:forms.confirm.description) }}' | ||
| variant: BODY_1 | ||
| - type: BLOCK | ||
| id: block_signout | ||
| components: | ||
| - type: ACTION | ||
| id: action_confirm | ||
| label: '{{ t(signout:forms.confirm.actions.submit.label) }}' | ||
| variant: PRIMARY | ||
| eventType: SUBMIT | ||
| prompts: | ||
| - action: | ||
| ref: action_confirm | ||
| nextNode: session_signout | ||
| - id: session_signout | ||
| type: TASK_EXECUTION | ||
| layout: | ||
| size: | ||
| width: 217 | ||
| height: 113 | ||
| position: | ||
| x: 960 | ||
| x: 463 |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
🔴 Documentation Required
This PR introduces user-facing changes that are not covered by documentation updates under docs/.
Please update the relevant documentation before merging.
Missing documentation:
- Default and console sign-out flows: Update the relevant sign-out flow guide under
docs/content/guides/to describe immediate default sign-out, the Silent Sign Out template, and Conditional Confirmation behavior. - OAuth logout POST parameters: Update
docs/content/apis.mdxto document form-encoded POST support for the logout endpoint and its accepted parameters.
📍 Affects 3 files
backend/cmd/server/bootstrap/01-default-resources.yaml#L578-L593(this comment)frontend/apps/console/src/features/flows/data/templates.json#L12898-L12963backend/internal/oauth/oauth2/logout/handler.go#L73-L75
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@backend/cmd/server/bootstrap/01-default-resources.yaml` around lines 578 -
593, The sign-out flow and OAuth logout behavior require documentation updates.
In the relevant sign-out guide under docs/content/guides/, document immediate
default sign-out, the Silent Sign Out template, and Conditional Confirmation
behavior; in docs/content/apis.mdx, document form-encoded POST support for the
logout endpoint and its accepted parameters. The YAML, templates.json, and
handler.go sites require no direct code changes.
Source: Path instructions
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Purpose
Signing out of the console required an extra confirmation click, and the RP-initiated logout request carried the user's ID token in the URL query string, where reverse proxies, load balancers, browser history and
Refererheaders all record it. This PR removes the confirmation step from the default sign-out experience, keeps the ID token out of logout URLs, and fixes a bug that made aPOSTto theend_session_endpointbehave differently from aGET.start -> prompt_confirm -> session_signout -> endtostart -> session_signout -> end. The prompt was unconditional, so this is what actually removes the click. Applies to every application on thedefault-flowsign-out handle, not just the console.id_token_hint.sendIdTokenInLogoutRequest: falsein the console's SDK defaults makes the SDK sendclient_idinstead. It sits insdkDefaults, so operators can still override it throughconfig.sdk.handler.gobuilt its parameter map fromr.URL.Query(). On a POST the parameters arrive in the body, so the map was empty and the sign-out flow'sInitiatorRequest.QueryParamsreceived nothing. Now sourced fromr.Form, whichParseFormpopulates from both the query string and the body.SessionSignOutExecutor, mirroring the new default. The existing "Confirm & Sign Out" and "Conditional Confirmation" templates are unchanged.Approach
Why drop
id_token_hintrather than keep it. The hint is optional in OIDC RP-Initiated Logout, and across the use cases we have seen it earns very little. ThunderID resolves the session to terminate from the per-flow SSO cookie, not from the hint. All the hint does is resolve the client id, whichclient_iddoes directly, and thepost_logout_redirect_uriis validated against the client's registered list either way. That leaves a signed token carrying identity claims sitting in a URL for no practical gain, so the console stops sending it. Having the SDK issue the sign-out as a POST is a worthwhile improvement in its own right and the backend already accepts both methods, but it is not a prerequisite for this change.Consequence worth reviewing. The one thing the hint bought is attribution. Per OIDC RP-Initiated Logout the OP must ask the End-User to confirm when no
id_token_hintis supplied, precisely because the request is then unattributable. With the prompt removed as well,/oauth2/logout?client_id=CONSOLE&post_logout_redirect_uri=...is a complete unauthenticated sign-out request: any page can navigate a signed-in user's browser to it and terminate their SSO session. The impact is nuisance-grade (forced logout, no data exposure), but reviewers should know it now applies to every application on the default flow.What was deliberately left alone. The
promptOnSignOutexecutor property and thelogoutPromptRequiredruntime key are untouched, so the conditional sign-out path still works for anyone who opts into it. Note that this conditional path is only reachable through/oauth2/logout: the flag has a single writer in the OAuth logout layer, so aSIGNOUTflow initiated directly throughPOST /flow/executenever prompts.Related Issues
Related PRs
Checklist
breaking changelabel added.Security checks
Summary by CodeRabbit
New Features
Bug Fixes
Updates