mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-24 16:46:33 +01:00
6 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9956a72694
|
🧭 fix: Subdirectory Deployment Auth Redirect Path Doubling (#12077)
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Waiting to run
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Waiting to run
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Blocked by required conditions
* fix: subdirectory redirects * fix: use path-segment boundary check when stripping BASE_URL prefix A bare `startsWith(BASE_URL)` matches on character prefix, not path segments. With BASE_URL="/chat", a path like "/chatroom/c/abc" would incorrectly strip to "room/c/abc" (no leading slash). Guard with an exact-match-or-slash check: `p === BASE_URL || p.startsWith(BASE_URL + '/')`. Also removes the dead `BASE_URL !== '/'` guard — module init already converts '/' to ''. * test: add path-segment boundary tests and clarify subdirectory coverage - Add /chatroom, /chatbot, /app/chatroom regression tests to verify BASE_URL stripping only matches on segment boundaries - Clarify useAuthRedirect subdirectory test documents React Router basename behavior (BASE_URL stripping tested in api-endpoints-subdir) - Use `delete proc.browser` instead of undefined assignment for cleanup - Add rationale to eslint-disable comment for isolateModules require * fix: use relative path and correct instructions in subdirectory test script - Replace hardcoded /home/danny/LibreChat/.env with repo-root-relative path so the script works from any checkout location - Update instructions to use production build (npm run build && npm run backend) since nginx proxies to :3080 which only serves the SPA after a full build, not during frontend:dev on :3090 * fix: skip pointless redirect_to=/ for root path and fix jsdom 26+ compat buildLoginRedirectUrl now returns plain /login when the resolved path is root — redirect_to=/ adds no value since / immediately redirects to /c/new after login anyway. Also rewrites api-endpoints.spec.ts to use window.history.replaceState instead of Object.defineProperty(window, 'location', ...) which jsdom 26+ no longer allows. * test: fix request-interceptor.spec.ts for jsdom 26+ compatibility Switch from jsdom to happy-dom environment which allows Object.defineProperty on window.location. jsdom 26+ made location non-configurable, breaking all 8 tests in this file. * chore: update browser property handling in api-endpoints-subdir test Changed the handling of the `proc.browser` property from deletion to setting it to false, ensuring compatibility with the current testing environment. * chore: update backend restart instructions in test subdirectory setup script Changed the instruction for restarting the backend from "npm run backend:dev" to "npm run backend" to reflect the correct command for the current setup. * refactor: ensure proper cleanup in loadModuleWithBase function Wrapped the module loading logic in a try-finally block to guarantee that the `proc.browser` property is reset to false and the base element is removed, improving reliability in the testing environment. * refactor: improve browser property handling in loadModuleWithBase function Revised the management of the `proc.browser` property to store the original value before modification, ensuring it is restored correctly after module loading. This enhances the reliability of the testing environment. |
||
|
|
0ef369af9b
|
📦 chore: npm audit bump (#12074)
* chore: npm audit - Bumped versions for several packages: `@hono/node-server` to 1.19.10, `@tootallnate/once` to 3.0.1, `hono` to 4.12.5, `serialize-javascript` to 7.0.4, and `svgo` to 2.8.2. - Removed deprecated `@trysound/sax` package from package-lock.json. - Updated integrity hashes and resolved URLs in package-lock.json to reflect the new versions. * chore: update dependencies and package versions - Bumped `jest-environment-jsdom` to version 30.2.0 in both package.json and client/package.json. - Updated related Jest packages to version 30.2.0 in package-lock.json, ensuring compatibility with the latest features and fixes. - Added `svgo` package with version 2.8.2 to package.json for improved SVG optimization. * chore: add @happy-dom/jest-environment and update test files - Added `@happy-dom/jest-environment` version 20.8.3 to `package.json` and `package-lock.json` for improved testing environment. - Updated test files to utilize the new Jest environment, replacing mock implementations of `window.location` with `window.history.replaceState` for better clarity and maintainability. - Refactored tests in `SourcesErrorBoundary`, `useFocusChatEffect`, `AuthContext`, and `StartupLayout` to enhance reliability and reduce complexity. |
||
|
|
b1771e0a6e
|
🌐 fix: Preserve URL Query Params Through Auth Refresh and Conversation Init (#12028)
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Waiting to run
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Waiting to run
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Blocked by required conditions
* 🔗 fix: Preserve URL query params during silent token refresh The silent token refresh on hard navigation was redirecting to '/c/new' without query params, wiping the URL before ChatRoute could read them. Now preserves the current URL (pathname + search) as the redirect fallback, with isSafeRedirect validation. * 🧭 fix: Apply URL query params in ChatRoute initialization ChatRoute now reads URL search params (endpoint, model, agent_id, etc.) and merges them into the preset passed to newConversation(), so the first conversation init already includes the URL param settings. This eliminates the race where useQueryParams fired too late. - Export processValidSettings from useQueryParams for reuse - Add getNewConvoPreset helper in ChatRoute (used in both NEW_CONVO branches) - Query params take precedence over model spec defaults - useQueryParams now waits for endpointsConfig before processing - Skip redundant newQueryConvo when settings are already applied - Clean all URL params via setSearchParams after processing * ✅ test: Update useQueryParams tests for new URL cleanup behavior - Assert setSearchParams called instead of window.history.replaceState - Mock endpoints config in deferred submission and timeout tests * ♻️ refactor: Move processValidSettings to ~/utils and address review findings - Move processValidSettings/parseQueryValue to createChatSearchParams.ts (pure utility, not hook-specific) - Fix processSubmission: use setSearchParams instead of replaceState, move URL cleanup outside data.text guard - Narrow endpointsConfig guard: only block settings application, not prompt-only flows - Convert areSettingsApplied to stable useCallback ([] deps) with conversationRef to avoid interval churn on conversation updates - Replace console.log with logger.log in production paths - Restore explanatory comment on pendingSubmitRef guard - Use for...of in processValidSettings (CLAUDE.md preference) - Remove unused imports from useQueryParams * 🔧 fix: Add areSettingsApplied to effect deps and fix test mocks - Restore areSettingsApplied in main effect deps (stable identity with [] deps, safe to include — satisfies exhaustive-deps lint rule) - Fix all test getQueryData mocks to properly distinguish between startupConfig and endpoints keys - Assert setSearchParams call arguments (URLSearchParams + replace:true) * ✅ test: Assert empty URLSearchParams in setSearchParams calls Tighten setSearchParams assertions to verify the params are empty (toString() === ''), not just that a URLSearchParams instance was passed. * 🔧 test: Update AuthContext tests to navigate to current URL for redirects - Modified test cases to assert navigation to the current URL instead of a hardcoded '/c/new' when no stored redirect exists or when falling back from unsafe stored redirects. - Enhanced test setup to define window.location for accurate simulation of redirect behavior. |
||
|
|
7c71875da3
|
🧭 fix: Restore Post-Auth Navigation After Silent Token Refresh (#12025)
* chore: Update import path for StartupLayout in tests * 🔒 fix: Enhance AuthContext to handle stored redirects during user authentication - Added SESSION_KEY import and logic to retrieve and clear stored redirect URLs from sessionStorage. - Updated user context state to include redirect URL, defaulting to '/c/new' if none is found. * 🧪 test: Add tests for silentRefresh post-login redirect handling in AuthContext - Introduced new test suite to validate navigation behavior after successful token refresh. - Implemented tests for stored sessionStorage redirects, default navigation, and prevention of unsafe redirects. - Enhanced logout error handling tests to ensure proper state clearing without external redirects. * 🔒 fix: Update AuthContext to handle unsafe stored redirects during authentication - Removed conditional check for stored redirect in sessionStorage, ensuring it is always cleared. - Enhanced logic to validate stored redirects, defaulting to '/c/new' for unsafe URLs. - Updated tests to verify navigation behavior for both safe and unsafe redirects after token refresh. |
||
|
|
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> |
||
|
|
0568f1c1eb
|
🪃 fix: Prevent Recursive Login Redirect Loop (#11964)
* fix: Prevent recursive login redirect loop
buildLoginRedirectUrl() would blindly encode the current URL into a
redirect_to param even when already on /login, causing infinite nesting
(/login?redirect_to=%2Flogin%3Fredirect_to%3D...). Guard at source so
it returns plain /login when pathname starts with /login.
Also validates redirect_to in the login error handler with isSafeRedirect
to close an open-redirect vector, and removes a redundant /login guard
from useAuthRedirect now handled by the centralized check.
* 🔀 fix: Handle basename-prefixed login paths and remove double URL decoding
buildLoginRedirectUrl now uses isLoginPath() which matches /login,
/librechat/login, and /login/2fa — covering subdirectory deployments
where window.location.pathname includes the basename prefix.
Remove redundant decodeURIComponent calls on URLSearchParams.get()
results (which already returns decoded values) in getPostLoginRedirect,
Login.tsx, and AuthContext login error handler. The extra decode could
throw URIError on inputs containing literal percent signs.
* 🔀 fix: Tighten login path matching and add onError redirect tests
Replace overbroad `endsWith('/login')` with a single regex
`/(^|\/)login(\/|$)/` that matches `/login` only as a full path
segment. Unifies `isSafeRedirect` and `buildLoginRedirectUrl` to use
the same `LOGIN_PATH_RE` constant — no more divergent definitions.
Add tests for the AuthContext onError redirect_to preservation logic
(valid path preserved, open-redirect blocked, /login loop blocked),
and a false-positive guard proving `/c/loginhistory` is not matched.
Update JSDoc on `buildLoginRedirectUrl` to document the plain `/login`
early-return, and add explanatory comment in AuthContext `onError`
for why `buildLoginRedirectUrl()` cannot be used there.
* test: Add unit tests for AuthContextProvider login error handling
Introduced a new test suite for AuthContextProvider to validate the handling of login errors and the preservation of redirect parameters. The tests cover various scenarios including valid redirect preservation, open-redirect prevention, and recursive redirect prevention. This enhances the robustness of the authentication flow and ensures proper navigation behavior during login failures.
|