LibreChat/packages/data-provider/src
Danny Avila b18915a96b
🚪 fix: Complete OIDC RP-Initiated Logout With id_token_hint and Redirect Race Fix (#12024)
* fix: complete OIDC logout implementation

The OIDC logout feature added in #5626 was incomplete:

1. Backend: Missing id_token_hint/client_id parameters required by the
   RP-Initiated Logout spec. Keycloak 18+ rejects logout without these.

2. Frontend: The logout redirect URL was passed through isSafeRedirect()
   which rejects all absolute URLs. The redirect was silently dropped.

Backend: Add id_token_hint (preferred) or client_id (fallback) to the
logout URL for OIDC spec compliance.

Frontend: Use window.location.replace() for logout redirects from the
backend, bypassing isSafeRedirect() which was designed for user-input
validation.

Fixes #5506

* fix: accept undefined in setTokenHeader to properly clear Authorization header

When token is undefined, delete the Authorization header instead of
setting it to "Bearer undefined". Removes the @ts-ignore workaround
in AuthContext.

* fix: skip axios 401 refresh when Authorization header is cleared

When the Authorization header has been removed (e.g. during logout),
the response interceptor now skips the token refresh flow. This
prevents a successful refresh from canceling an in-progress OIDC
external redirect via window.location.replace().

* fix: guard against undefined OPENID_CLIENT_ID in logout URL

Prevent literal "client_id=undefined" in the OIDC end-session URL
when OPENID_CLIENT_ID is not set. Log a warning when neither
id_token_hint nor client_id is available.

* fix: prevent race condition canceling OIDC logout redirect

The logout mutation wrapper's cleanup (clearStates, removeQueries)
triggers re-renders and 401s on in-flight requests. The axios
interceptor would refresh the token successfully, firing
dispatchTokenUpdatedEvent which cancels the window.location.replace()
navigation to the IdP's end_session_endpoint.

Fix:
- Clear Authorization header synchronously before redirect so the
  axios interceptor skips refresh for post-logout 401s
- Add isExternalRedirectRef to suppress silentRefresh and useEffect
  side effects during the redirect
- Add JSDoc explaining why isSafeRedirect is bypassed

* test: add LogoutController and AuthContext logout test coverage

LogoutController.spec.js (13 tests):
- id_token_hint from session and cookie fallback
- client_id fallback, including undefined OPENID_CLIENT_ID guard
- Disabled endpoint, missing issuer, non-OpenID user
- post_logout_redirect_uri (custom and default)
- Missing OpenID config and end_session_endpoint
- Error handling and cookie clearing

AuthContext.spec.tsx (3 tests):
- OIDC redirect calls window.location.replace + setTokenHeader
- Non-redirect logout path
- Logout error handling

* test: add coverage for setTokenHeader, axios interceptor guard, and silentRefresh suppression

headers-helpers.spec.ts (3 tests):
- Sets Authorization header with Bearer token
- Deletes Authorization header when called with undefined
- No-op when clearing an already absent header

request-interceptor.spec.ts (2 tests):
- Skips refresh when Authorization header is cleared (the race fix)
- Attempts refresh when Authorization header is present

AuthContext.spec.tsx (1 new test):
- Verifies silentRefresh is not triggered after OIDC redirect

* test: enhance request-interceptor tests with adapter restoration and refresh verification

- Store the original axios adapter before tests and restore it after all tests to prevent side effects.
- Add verification for the refresh endpoint call in the interceptor tests to ensure correct behavior during token refresh attempts.

* test: enhance AuthContext tests with live rendering and improved logout error handling

- Introduced a new `renderProviderLive` function to facilitate testing with silentRefresh.
- Updated tests to use the live rendering function, ensuring accurate simulation of authentication behavior.
- Enhanced logout error handling test to verify that auth state is cleared without external redirects.

* test: update LogoutController tests for OpenID config error handling

- Renamed test suite to clarify that it handles cases when OpenID config is not available.
- Modified test to check for error thrown by getOpenIdConfig instead of returning null, ensuring proper logging of the error message.

* refactor: improve OpenID config error handling in LogoutController

- Simplified error handling for OpenID configuration retrieval by using a try-catch block.
- Updated logging to provide clearer messages when the OpenID config is unavailable.
- Ensured that the end session endpoint is only accessed if the OpenID config is successfully retrieved.

---------

Co-authored-by: cloudspinner <stijn.tastenhoye@gmail.com>
2026-03-02 21:34:13 -05:00
..
react-query 🛸 feat: Remote Agent Access with External API Support (#11503) 2026-01-28 17:44:33 -05:00
types 📄 feat: Local Text Extraction for PDF, DOCX, and XLS/XLSX (#11900) 2026-02-22 14:22:45 -05:00
accessPermissions.ts 🛸 feat: Remote Agent Access with External API Support (#11503) 2026-01-28 17:44:33 -05:00
actions.ts 🛡️ fix: Implement TOCTOU-Safe SSRF Protection for Actions and MCP (#11722) 2026-02-11 22:09:58 -05:00
api-endpoints.ts 🛡️ fix: Secure MCP/Actions OAuth Flows, Resolve Race Condition & Tool Cache Cleanup (#11756) 2026-02-12 14:22:05 -05:00
artifacts.ts 🪟 fix: Windows Build (npm) (#3889) 2024-09-02 10:01:09 -04:00
azure.ts 🔃 refactor: Decouple Effects from AppService, move to data-schemas (#9974) 2025-10-05 06:37:57 -04:00
bedrock.ts 🧠 feat: Add reasoning_effort configuration for Bedrock models (#11991) 2026-02-28 15:02:09 -05:00
config.ts 🎚️ feat: Add Thinking Level Parameter for Gemini 3+ Models (#11994) 2026-02-28 16:56:10 -05:00
createPayload.ts ⏸ refactor: Improve UX for Parallel Streams (Multi-Convo) (#11096) 2025-12-25 01:43:54 -05:00
data-service.ts 🛡️ fix: Secure MCP/Actions OAuth Flows, Resolve Race Condition & Tool Cache Cleanup (#11756) 2026-02-12 14:22:05 -05:00
feedback.ts 📈 feat: Chat rating for feedback (#5878) 2025-05-30 12:16:34 -04:00
file-config.spec.ts 🧩 feat: OpenDocument Format File Upload and Native ODS Parsing (#11959) 2026-02-26 14:39:49 -05:00
file-config.ts 🧩 feat: OpenDocument Format File Upload and Native ODS Parsing (#11959) 2026-02-26 14:39:49 -05:00
generate.ts 🪐 feat: Initial OpenAI Responses API Support (#8149) 2025-06-30 18:34:47 -04:00
headers-helpers.ts 🚪 fix: Complete OIDC RP-Initiated Logout With id_token_hint and Redirect Race Fix (#12024) 2026-03-02 21:34:13 -05:00
index.ts 📡 refactor: MCP Runtime Config Sync with Redis Distributed Locking (#10352) 2025-12-11 16:36:15 -05:00
keys.ts 🛸 feat: Remote Agent Access with External API Support (#11503) 2026-01-28 17:44:33 -05:00
mcp.ts ⏱️ fix: Separate MCP GET SSE Stream Timeout from POST and Suppress SDK-Internal Recovery Errors (#11936) 2026-02-24 21:05:58 -05:00
messages.ts 🐛 fix: String Interpolation in Messages Endpoint from #9155 (#9312) 2025-08-27 13:48:48 -04:00
models.ts 🗂️ refactor: Artifacts via Model Specs & Scope Badge Persistence by Spec Context (#11796) 2026-02-14 13:56:50 -05:00
parameterSettings.ts 🎚️ feat: Add Thinking Level Parameter for Gemini 3+ Models (#11994) 2026-02-28 16:56:10 -05:00
parsers.ts 📅 refactor: Replace Numeric Weekday Index with Named Day in Date Template Variables (#12022) 2026-03-02 19:22:11 -05:00
permissions.ts 🛸 feat: Remote Agent Access with External API Support (#11503) 2026-01-28 17:44:33 -05:00
request.ts 🚪 fix: Complete OIDC RP-Initiated Logout With id_token_hint and Redirect Race Fix (#12024) 2026-03-02 21:34:13 -05:00
roles.ts 🛸 feat: Remote Agent Access with External API Support (#11503) 2026-01-28 17:44:33 -05:00
schemas.spec.ts 🤖 feat: Claude Opus 4.6 - 1M Context, Premium Pricing, Adaptive Thinking (#11670) 2026-02-06 18:35:36 -05:00
schemas.ts 🎚️ feat: Add Thinking Level Parameter for Gemini 3+ Models (#11994) 2026-02-28 16:56:10 -05:00
types.ts 🎚️ feat: Add Thinking Level Parameter for Gemini 3+ Models (#11994) 2026-02-28 16:56:10 -05:00
utils.ts 📂 refactor: Cleanup File Filtering Logic, Improve Validation (#10414) 2025-11-10 19:05:30 -05:00