Derive the end session endpoint from the server's logout path - #43
Conversation
The baseUrl-derived endpoint defaults are used whenever OIDC discovery cannot be consumed, but END_SESSION pointed at /oidc/logout, which the server does not serve. Sign-out then hit an unrouted path and came back as a 401 instead of starting the logout flow. Point it at /oauth2/logout, matching the end_session_endpoint advertised in the discovery document, and log a warning whenever discovery is skipped so the fallback is no longer silent.
📝 WalkthroughWalkthroughOIDC logout endpoint derivation now uses ChangesOIDC endpoint resolution
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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
🧹 Nitpick comments (2)
packages/javascript/src/__tests__/AuthenticationHelper.test.ts (1)
62-72: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winProtect the unchanged
SESSION_IFRAMEendpoint with an assertion.This case claims to derive every endpoint but omits
check_session_iframe. Add an assertion or rename the test so the coverage claim is accurate.Suggested assertion
expect(endpoints.issuer).toBe(BASE_URL); + expect(endpoints.check_session_iframe).toBe(`${BASE_URL}/oidc/checksession`);This also protects the PR’s stated unchanged
SESSION_IFRAMEcontract.🤖 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 `@packages/javascript/src/__tests__/AuthenticationHelper.test.ts` around lines 62 - 72, Update the resolveEndpointsByBaseURL() test to assert that check_session_iframe retains the expected SESSION_IFRAME value, preserving the unchanged endpoint contract while keeping the “derives every endpoint” coverage claim accurate.packages/javascript/src/ThunderIDJavaScriptClient.ts (1)
359-390: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd regression tests for the new discovery diagnostics.
The supplied tests do not exercise fetch failures, non-200 responses, or malformed discovery responses. Verify both
logger.warncalls and that base-URL-derived metadata is persisted after each recoverable failure.🤖 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 `@packages/javascript/src/ThunderIDJavaScriptClient.ts` around lines 359 - 390, Add regression tests for the discovery flow covering fetch rejection, non-200 responses, and malformed discovery payloads. For each recoverable failure, assert the corresponding logger.warn call and verify base-URL-derived metadata is persisted, while preserving the existing successful discovery behavior.
🤖 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 `@packages/javascript/src/ThunderIDJavaScriptClient.ts`:
- Around line 362-373: Update the warning messages in the discovery
response-status and catch branches of ThunderIDJavaScriptClient so they do not
unconditionally promise a base-URL fallback. Make the wording conditional on
baseUrl being configured, or state that fallback will be attempted only when
available, while preserving the existing fallback and error behavior.
---
Nitpick comments:
In `@packages/javascript/src/__tests__/AuthenticationHelper.test.ts`:
- Around line 62-72: Update the resolveEndpointsByBaseURL() test to assert that
check_session_iframe retains the expected SESSION_IFRAME value, preserving the
unchanged endpoint contract while keeping the “derives every endpoint” coverage
claim accurate.
In `@packages/javascript/src/ThunderIDJavaScriptClient.ts`:
- Around line 359-390: Add regression tests for the discovery flow covering
fetch rejection, non-200 responses, and malformed discovery payloads. For each
recoverable failure, assert the corresponding logger.warn call and verify
base-URL-derived metadata is persisted, while preserving the existing successful
discovery behavior.
🪄 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: 63566f92-4341-417d-9948-36715849efef
📒 Files selected for processing (3)
packages/javascript/src/ThunderIDJavaScriptClient.tspackages/javascript/src/__tests__/AuthenticationHelper.test.tspackages/javascript/src/constants/OIDCDiscoveryConstants.ts
| logger.warn( | ||
| `ThunderIDJavaScriptClient: Discovery request to ${resolvedWellKnownEndpoint} returned ` + | ||
| `${response.status}; falling back to endpoints derived from the base URL.`, | ||
| ); | ||
| response = undefined; | ||
| } | ||
| } catch { | ||
| } catch (error: unknown) { | ||
| logger.warn( | ||
| `ThunderIDJavaScriptClient: Discovery request to ${resolvedWellKnownEndpoint} failed; ` + | ||
| 'falling back to endpoints derived from the base URL.', | ||
| error, | ||
| ); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Do not promise a base-URL fallback when baseUrl is absent.
These warnings always say “falling back,” but the subsequent branches throw JS-AUTH_CORE-GOPMD-HE01 when no baseUrl is configured. Make the message conditional or state that a fallback will be attempted only when available.
Also applies to: 384-390
🤖 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 `@packages/javascript/src/ThunderIDJavaScriptClient.ts` around lines 362 - 373,
Update the warning messages in the discovery response-status and catch branches
of ThunderIDJavaScriptClient so they do not unconditionally promise a base-URL
fallback. Make the wording conditional on baseUrl being configured, or state
that fallback will be attempted only when available, while preserving the
existing fallback and error behavior.
Purpose
OIDCDiscoveryConstants.Endpoints.END_SESSIONdefaulted to/oidc/logout, which the server does not serve. These baseUrl-derived defaults are used whenever OIDC discovery cannot be consumed, so in that situationsignOut()sent the browser to an unrouted path and the request came back as401 AUTH-4010("Authentication is required to access this resource") instead of starting the logout flow.Every other derived default already matches the server (
/oauth2/authorize,/oauth2/token,/oauth2/jwks,/oauth2/revoke,/oauth2/userinfo), and the discovery document advertisesend_session_endpointas<baseUrl>/oauth2/logout.END_SESSIONwas the one that didn't.Reproduced against a local server:
GET /oidc/logout-> 401 AUTH-4010GET /oauth2/logout-> 302 to the sign-out gateApproach
END_SESSIONat/oauth2/logout, matching the advertisedend_session_endpoint.loadOpenIDProviderConfiguration()on each of the three ways discovery can degrade (fetch threw, non-200 response, unparseable response). Previously all three were swallowed by barecatch {}blocks, the baseUrl fallback was cached behindop_config_initiated, and nothing surfaced. That silence is what made this hard to diagnose: sign-in still worked, because authorize/token resolve to the same paths either way, soEND_SESSIONwas the only endpoint where the fallback diverged from reality.AuthenticationHelper.test.tscoveringresolveEndpointsByBaseURL(), which had no test coverage. The existinggetSignOutUrl()tests seed provider metadata directly, so they could not have caught this. Verified the new test fails against the old constant:expected 'https://localhost:8090/oidc/logout' to be 'https://localhost:8090/oauth2/logout'.Note:
SESSION_IFRAMEis also wrong (/oidc/checksessionis not served andcheck_session_iframeis never advertised), but there is no correct path to repoint it at, and it is threaded through theOIDCDiscoveryConstantstype andresolveEndpointsExplicitly's required-endpoints list. Left for a separate change.Related Issues
Related PRs
Checklist
breaking changelabel added.Security checks
Summary by CodeRabbit