Skip to content

Add direct SSO redirect and backend logout#3590

Merged
Alex-Tideman merged 3 commits into
mainfrom
oss-oidc-improvements
Jun 24, 2026
Merged

Add direct SSO redirect and backend logout#3590
Alex-Tideman merged 3 commits into
mainfrom
oss-oidc-improvements

Conversation

@Alex-Tideman

@Alex-Tideman Alex-Tideman commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Description & motivation 💭

This PR improves the OIDC authentication flow for self-hosted Temporal UI deployments.

It adds a new auth.redirectToProvider server configuration option that allows deployments to skip the intermediate Temporal UI /login page and send unauthenticated users directly to the configured OIDC provider through /auth/sso. This is useful for environments that want an IdP-first login flow and currently need proxy-level workarounds to bypass the "Continue to SSO" page.

It also updates UI logout behavior to call the existing /auth/logout backend endpoint instead of only clearing client state and navigating to /login. Calling the backend endpoint lets the server clear the refresh, session, and user cookies so the browser is actually logged out of the Temporal UI session.

Implementation details:

  • Added auth.redirectToProvider to server config, Docker config, auth docs, and the /api/v1/settings auth response.
  • Added TEMPORAL_AUTH_REDIRECT_TO_PROVIDER support for Docker config.
  • Mapped RedirectToProvider into frontend settings as settings.auth.redirectToProvider, defaulting to false for compatibility with older settings responses.
  • Updated unauthenticated app-route redirects to use /auth/sso when redirectToProvider is enabled.
  • Updated /login route loading so direct visits also redirect to /auth/sso when the flag is enabled.
  • Updated 401/403 handling to respect the same redirect setting.
  • Updated the user-menu logout action to call /auth/logout with credentials before clearing local auth state and navigating home.

Screenshots (if applicable) 📸

RedirectToProvider.mov

Design Considerations 🎨

No design review needed. The default behavior remains the existing /login page with the "Continue to SSO" step. The new direct provider redirect only applies when auth.redirectToProvider is explicitly enabled.

Testing 🧪

How was this tested 👻

  • Manual testing
  • E2E tests added
  • Unit tests added

Added/updated tests for:

  • Server settings response includes Auth.RedirectToProvider.
  • Frontend settings service maps RedirectToProvider and defaults it to false.
  • Route helpers return /login by default and /auth/sso with returnUrl when direct provider redirects are enabled.
  • Base-path behavior for the new auth redirect helper.
  • 401/403 error handling respects redirectToProvider.
  • UI logout calls /auth/logout, includes credentials, clears local auth state, and navigates home.
  • Playwright OAuth flow coverage for default unauthenticated redirect, direct SSO redirect, and backend logout invocation.

Validated locally with:

pnpm test src/lib/utilities/route-for.test.ts src/lib/utilities/route-for-base-path.test.ts src/lib/services/settings-service.test.ts src/lib/utilities/handle-error.test.ts src/lib/stores/auth-user.test.ts
go test ./server/api
pnpm check
PW_MODE=integration pnpm exec playwright test tests/integration/oauth-flow.spec.ts --project "chromium desktop"
git diff --check

pnpm check reported 0 errors. Existing Svelte warnings remain.

Steps for others to test: 🚶🏽‍♂️🚶🏽‍♀️

  1. Configure OIDC auth normally and leave auth.redirectToProvider unset or set to false.
  2. Run ui with pnpm dev:with-auth
  3. Visit a protected UI route while unauthenticated.
  4. Confirm the UI still redirects to /login and shows the existing "Continue to SSO" flow.
  5. Set auth.redirectToProvider: true or, for Docker config, TEMPORAL_AUTH_REDIRECT_TO_PROVIDER=true.
  6. Restart the UI server and visit a protected UI route while unauthenticated.
  7. Confirm the browser is redirected directly to /auth/sso and the original route is preserved in returnUrl.
  8. Log in, then use the user-menu logout action.
  9. Confirm the browser requests /auth/logout, the server clears auth cookies, and the UI navigates home.

Checklists

Draft Checklist

Ready for review.

Merge Checklist

  • CI passes

Issue(s) closed

Closes #3578
Closes #3579

Docs

Any docs updates needed?

Updated AUTHENTICATION.md with the new redirectToProvider auth setting.

@Alex-Tideman
Alex-Tideman requested a review from a team as a code owner June 23, 2026 16:23
@vercel

vercel Bot commented Jun 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
holocene Ready Ready Preview, Comment Jun 23, 2026 5:16pm

Request Review

@temporal-cicd

temporal-cicd Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor
Warnings
⚠️

📊 Strict Mode: 1 error in 1 file (0.1% of 892 total)

src/lib/services/settings-service.ts (1)
  • L75:2: Type '{ auth: { enabled: boolean; options: string[] | null; redirectToProvider: boolean; }; baseUrl: string | null; codec: { endpoint: string; passAccessToken: boolean | undefined; includeCredentials: boolean | undefined; customErrorMessage: { ...; }; }; ... 17 more ...; version: string; }' is not assignable to type 'Settings'.

Generated by 🚫 dangerJS against fd01efb

@GraceGardner GraceGardner left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for getting on this so fast

@Alex-Tideman
Alex-Tideman merged commit 9c6fcd5 into main Jun 24, 2026
23 checks passed
@Alex-Tideman
Alex-Tideman deleted the oss-oidc-improvements branch June 24, 2026 14:36
temporal-cicd Bot pushed a commit that referenced this pull request Jul 2, 2026
Auto-generated version bump from 2.51.1 to 2.52.0

Bump type: minor

Changes included:
- [`9c6fcd54`](9c6fcd5) Add direct SSO redirect and backend logout (#3590)
- [`feab0d90`](feab0d9) a11y(4.1.3): Toaster role="log" → per-toast role="status"/"alert" for correct AT announcement semantics (#3560)
- [`d7bbfb01`](d7bbfb0) a11y(2.5.8): toast — replace bare close button with IconButton (36×36 px) (#3553)
- [`4efd6ab6`](4efd6ab) a11y(3.3.1): Holocene input primitives — add aria-invalid, aria-describedby, and uniform live-region error announcement (#3554)
- [`0600b700`](0600b70) Use green only (#3599)
- [`94107549`](9410754) Clarify activity pause timeout behavior (#3600)
- [`9f88d5a8`](9f88d5a) Bump node version to 22.23.1 or newer to fix issue from previous security release (#3604)
- [`ca4104ae`](ca4104a) Update reason copy and inputs (#3588)
- [`51db73fa`](51db73f) Update batch operation reason input hint (#3605)
- [`836d7c55`](836d7c5) a11y(2.4.3): route navigation — move focus to the main landmark on afterNavigate, not just scroll (#3538)
- [`4ee95696`](4ee9569) Improve re-renders for large encoded event histories (#3592)
- [`fa5e7aa1`](fa5e7aa) feature/schedules (#3603)
- [`0d9467fd`](0d9467f) Default includeHeartbeatDetails and includeLastFailure to true for getActivityExecution and pollActivityExecution (#3521)
- [`e5bc514e`](e5bc514) fix schedules: duplicate key (#3612)
- [`f1eb489f`](f1eb489) Remove preview badge (#3581)
- [`1e5173b4`](1e5173b) Add existing versions to worker create deployment version form (#3601)
- [`a8552bae`](a8552ba) fix schedules -e.trim not a function (#3613)
- [`0442f847`](0442f84) Fix width of ComputeBadge in VersionTableRow (#3615)
- [`ddbeb54f`](ddbeb54) fix(cloud-nav): animate and stabilize side-nav collapse (#3606)
- [`3cfc684b`](3cfc684) fix - schedules recent/upcoming runs - sort issue (#3616)
- [`92b8875b`](92b8875) Move timestamp out of translate (#3617)
- [`901258af`](901258a) Fix SAA and WF consistency (#3614)
- [`99593d97`](99593d9) DT-4001 - standalone nexus operations (#3496)
- [`f10d1bf1`](f10d1bf) Clamp codeblock to container width (#3621)
- [`0a9d93ce`](0a9d93c) Remove unnecessary bottom-0 (#3623)
- [`9dabb522`](9dabb52) chore(deps-dev): bump vite from 6.4.2 to 6.4.3 (#3610)
- [`5c1854d3`](5c1854d) News Feed (#3596)
temporal-cicd Bot pushed a commit that referenced this pull request Jul 8, 2026
Auto-generated version bump from 2.51.1 to 2.52.0

Bump type: minor

Changes included:
- [`9c6fcd54`](9c6fcd5) Add direct SSO redirect and backend logout (#3590)
- [`feab0d90`](feab0d9) a11y(4.1.3): Toaster role="log" → per-toast role="status"/"alert" for correct AT announcement semantics (#3560)
- [`d7bbfb01`](d7bbfb0) a11y(2.5.8): toast — replace bare close button with IconButton (36×36 px) (#3553)
- [`4efd6ab6`](4efd6ab) a11y(3.3.1): Holocene input primitives — add aria-invalid, aria-describedby, and uniform live-region error announcement (#3554)
- [`0600b700`](0600b70) Use green only (#3599)
- [`94107549`](9410754) Clarify activity pause timeout behavior (#3600)
- [`9f88d5a8`](9f88d5a) Bump node version to 22.23.1 or newer to fix issue from previous security release (#3604)
- [`ca4104ae`](ca4104a) Update reason copy and inputs (#3588)
- [`51db73fa`](51db73f) Update batch operation reason input hint (#3605)
- [`836d7c55`](836d7c5) a11y(2.4.3): route navigation — move focus to the main landmark on afterNavigate, not just scroll (#3538)
- [`4ee95696`](4ee9569) Improve re-renders for large encoded event histories (#3592)
- [`fa5e7aa1`](fa5e7aa) feature/schedules (#3603)
- [`0d9467fd`](0d9467f) Default includeHeartbeatDetails and includeLastFailure to true for getActivityExecution and pollActivityExecution (#3521)
- [`e5bc514e`](e5bc514) fix schedules: duplicate key (#3612)
- [`f1eb489f`](f1eb489) Remove preview badge (#3581)
- [`1e5173b4`](1e5173b) Add existing versions to worker create deployment version form (#3601)
- [`a8552bae`](a8552ba) fix schedules -e.trim not a function (#3613)
- [`0442f847`](0442f84) Fix width of ComputeBadge in VersionTableRow (#3615)
- [`ddbeb54f`](ddbeb54) fix(cloud-nav): animate and stabilize side-nav collapse (#3606)
- [`3cfc684b`](3cfc684) fix - schedules recent/upcoming runs - sort issue (#3616)
- [`92b8875b`](92b8875) Move timestamp out of translate (#3617)
- [`901258af`](901258a) Fix SAA and WF consistency (#3614)
- [`99593d97`](99593d9) DT-4001 - standalone nexus operations (#3496)
- [`f10d1bf1`](f10d1bf) Clamp codeblock to container width (#3621)
- [`0a9d93ce`](0a9d93c) Remove unnecessary bottom-0 (#3623)
- [`9dabb522`](9dabb52) chore(deps-dev): bump vite from 6.4.2 to 6.4.3 (#3610)
- [`5c1854d3`](5c1854d) News Feed (#3596)
- [`340da30f`](340da30) a11y(2.1.1): guard global r/R keydown so text inputs can receive the letter (#3589)
- [`dd97a9d1`](dd97a9d) fix(markdown-editor): disable chromatic snapshot for preview story (#3631)
- [`7db61ab9`](7db61ab) a11y(4.1.2): Table / ProgressBar / Loading primitives — expose aria-busy on data-refresh regions (#3555)
- [`d2111ecf`](d2111ec) a11y(4.1.3): Add live-region wrappers for workflow status, event count, filter counts, and Banner (#3561)
- [`24eabaec`](24eabae) a11y(2.4.6): guard DrawerContent against empty <h2> when title is omitted (#3595)
- [`3552e307`](3552e30) Fix CodeMirror Lezer dependency mismatch (#3632)
- [`7ac37199`](7ac3719) Update defaults to match workflow defaults (#3634)
- [`c1f02865`](c1f0286) Draft fix for link variant handling (#3620)
- [`bbbf2b8c`](bbbf2b8) Add connection status and optional Latest Version column to deployments (DT-4174) (#3618)
- [`76f266f4`](76f266f) DurationInput updates (#3633)
- [`07da53c5`](07da53c) COM-191 - prefill CloudFormation template params in Launch Stack link (#3619)
- [`90946e0b`](90946e0) Schedules - Timeout empty defaults (#3637)
- [`97f9ad39`](97f9ad3) fix(cloud-nav): smooth label fade on side-nav collapse/expand (#3628)
- [`a399ed35`](a399ed3) Improve Search Attribute deletion messaging (#3629)
- [`ad976d94`](ad976d9) Pass through source prop for News Feed Widget (#3638)
- [`6ef84fe3`](6ef84fe) Restrict select-all to exclude workflow status (#3639)
- [`4c3729f8`](4c3729f) Reduce news feed markdown whitespace (#3642)
- [`aa04a9b6`](aa04a9b) feat(nexus-operations): add loading state to standalone nexus operations list page header (#3643)
- [`dce2f804`](dce2f80) chore: remove unused generate-holocene-props script (#3644)
- [`760bc7bc`](760bc7b) Make megaphone icon bigger (#3645)
- [`c047384a`](c047384) refactor(nexus): replace hand-rolled types with @temporalio/proto (#3646)
rossedfort added a commit that referenced this pull request Jul 8, 2026
Auto-generated version bump from 2.51.1 to 2.52.0

Bump type: minor

Changes included:
- [`9c6fcd54`](9c6fcd5) Add direct SSO redirect and backend logout (#3590)
- [`feab0d90`](feab0d9) a11y(4.1.3): Toaster role="log" → per-toast role="status"/"alert" for correct AT announcement semantics (#3560)
- [`d7bbfb01`](d7bbfb0) a11y(2.5.8): toast — replace bare close button with IconButton (36×36 px) (#3553)
- [`4efd6ab6`](4efd6ab) a11y(3.3.1): Holocene input primitives — add aria-invalid, aria-describedby, and uniform live-region error announcement (#3554)
- [`0600b700`](0600b70) Use green only (#3599)
- [`94107549`](9410754) Clarify activity pause timeout behavior (#3600)
- [`9f88d5a8`](9f88d5a) Bump node version to 22.23.1 or newer to fix issue from previous security release (#3604)
- [`ca4104ae`](ca4104a) Update reason copy and inputs (#3588)
- [`51db73fa`](51db73f) Update batch operation reason input hint (#3605)
- [`836d7c55`](836d7c5) a11y(2.4.3): route navigation — move focus to the main landmark on afterNavigate, not just scroll (#3538)
- [`4ee95696`](4ee9569) Improve re-renders for large encoded event histories (#3592)
- [`fa5e7aa1`](fa5e7aa) feature/schedules (#3603)
- [`0d9467fd`](0d9467f) Default includeHeartbeatDetails and includeLastFailure to true for getActivityExecution and pollActivityExecution (#3521)
- [`e5bc514e`](e5bc514) fix schedules: duplicate key (#3612)
- [`f1eb489f`](f1eb489) Remove preview badge (#3581)
- [`1e5173b4`](1e5173b) Add existing versions to worker create deployment version form (#3601)
- [`a8552bae`](a8552ba) fix schedules -e.trim not a function (#3613)
- [`0442f847`](0442f84) Fix width of ComputeBadge in VersionTableRow (#3615)
- [`ddbeb54f`](ddbeb54) fix(cloud-nav): animate and stabilize side-nav collapse (#3606)
- [`3cfc684b`](3cfc684) fix - schedules recent/upcoming runs - sort issue (#3616)
- [`92b8875b`](92b8875) Move timestamp out of translate (#3617)
- [`901258af`](901258a) Fix SAA and WF consistency (#3614)
- [`99593d97`](99593d9) DT-4001 - standalone nexus operations (#3496)
- [`f10d1bf1`](f10d1bf) Clamp codeblock to container width (#3621)
- [`0a9d93ce`](0a9d93c) Remove unnecessary bottom-0 (#3623)
- [`9dabb522`](9dabb52) chore(deps-dev): bump vite from 6.4.2 to 6.4.3 (#3610)
- [`5c1854d3`](5c1854d) News Feed (#3596)
- [`340da30f`](340da30) a11y(2.1.1): guard global r/R keydown so text inputs can receive the letter (#3589)
- [`dd97a9d1`](dd97a9d) fix(markdown-editor): disable chromatic snapshot for preview story (#3631)
- [`7db61ab9`](7db61ab) a11y(4.1.2): Table / ProgressBar / Loading primitives — expose aria-busy on data-refresh regions (#3555)
- [`d2111ecf`](d2111ec) a11y(4.1.3): Add live-region wrappers for workflow status, event count, filter counts, and Banner (#3561)
- [`24eabaec`](24eabae) a11y(2.4.6): guard DrawerContent against empty <h2> when title is omitted (#3595)
- [`3552e307`](3552e30) Fix CodeMirror Lezer dependency mismatch (#3632)
- [`7ac37199`](7ac3719) Update defaults to match workflow defaults (#3634)
- [`c1f02865`](c1f0286) Draft fix for link variant handling (#3620)
- [`bbbf2b8c`](bbbf2b8) Add connection status and optional Latest Version column to deployments (DT-4174) (#3618)
- [`76f266f4`](76f266f) DurationInput updates (#3633)
- [`07da53c5`](07da53c) COM-191 - prefill CloudFormation template params in Launch Stack link (#3619)
- [`90946e0b`](90946e0) Schedules - Timeout empty defaults (#3637)
- [`97f9ad39`](97f9ad3) fix(cloud-nav): smooth label fade on side-nav collapse/expand (#3628)
- [`a399ed35`](a399ed3) Improve Search Attribute deletion messaging (#3629)
- [`ad976d94`](ad976d9) Pass through source prop for News Feed Widget (#3638)
- [`6ef84fe3`](6ef84fe) Restrict select-all to exclude workflow status (#3639)
- [`4c3729f8`](4c3729f) Reduce news feed markdown whitespace (#3642)
- [`aa04a9b6`](aa04a9b) feat(nexus-operations): add loading state to standalone nexus operations list page header (#3643)
- [`dce2f804`](dce2f80) chore: remove unused generate-holocene-props script (#3644)
- [`760bc7bc`](760bc7b) Make megaphone icon bigger (#3645)
- [`c047384a`](c047384) refactor(nexus): replace hand-rolled types with @temporalio/proto (#3646)

Co-authored-by: rossedfort <[email protected]>
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 through ui navigates to /login via history.pushState Add passThroughProvider option to skip intermediate SSO page

2 participants