Skip to content
This repository was archived by the owner on Jul 8, 2026. It is now read-only.

Prevent return 302 on metadata resource urls - #187

Merged
mdthorpe-sc merged 3 commits into
mainfrom
mdthorpe/sc-310534/remove-302-well-known-oauth-redirect-and-serve
Mar 24, 2026
Merged

mdthorpe-sc merged 3 commits into
mainfrom
mdthorpe/sc-310534/remove-302-well-known-oauth-redirect-and-serve

Conversation

@mdthorpe-sc

@mdthorpe-sc mdthorpe-sc commented Mar 24, 2026

Copy link
Copy Markdown
Collaborator

Hopefully a fix for Claude

Summary by CodeRabbit

  • New Features

    • Well-known protected-resource endpoints now serve local JSON metadata (resource identifier, authorization servers, supported scopes) instead of redirecting upstream.
  • Tests

    • Added tests to validate the protected-resource metadata responses and confirm consistency between the root and MCP well-known endpoints.

@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@mdthorpe-sc has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 9 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1c52d7fe-bec3-45a6-ad0e-0fe8d6e11f8d

📥 Commits

Reviewing files that changed from the base of the PR and between e9ea977 and a81854e.

📒 Files selected for processing (2)
  • src/auth/oauth-integration.test.ts
  • src/auth/oauth.test.ts
📝 Walkthrough

Walkthrough

Replaced upstream redirects for OAuth protected-resource well-known endpoints with local JSON metadata responses. Added getProtectedResourceMetadata(config) and adjusted getWellKnownRedirectUrl to only handle authorization-server paths; tests updated to assert identical metadata from both protected-resource endpoints.

Changes

Cohort / File(s) Summary
Core Implementation
src/server-http.ts
Added exported getProtectedResourceMetadata(config) returning { resource, authorization_servers, scopes_supported }. Removed protected-resource handling from getWellKnownRedirectUrl. Routing now serves protected-resource metadata as JSON for /.well-known/oauth-protected-resource and /.well-known/oauth-protected-resource/mcp; /.well-known/oauth-authorization-server remains a redirect.
Tests — auth
src/auth/oauth.test.ts, src/auth/oauth-integration.test.ts
Added "Metadata Discovery" tests that concurrently fetch /.well-known/oauth-protected-resource and /.well-known/oauth-protected-resource/mcp, assert HTTP 200, parse JSON as ResourceMetadataResponse, and expect the two payloads to be equal.
Tests — server HTTP
src/server-http.test.ts
Imported and exercised getProtectedResourceMetadata; replaced prior redirect-based assertion with checks that metadata is computed from config.mcpServerUrl, config.authServerIssuerUrl, and process.env.AUTH_SERVER. Also added assertions that protected-resource paths return null from getWellKnownRedirectUrl under authorization-server config.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped to the well-known door,
Served JSON here, no redirect chore,
Two endpoints, one mirrored song,
Metadata tidy, tidy and strong —
Happy hops where responses belong! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Prevent return 302 on metadata resource urls' directly describes the main change: replacing 302 redirects with local JSON responses for protected resource metadata endpoints.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mdthorpe/sc-310534/remove-302-well-known-oauth-redirect-and-serve

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/server-http.test.ts (1)

201-221: Env manipulation is unnecessary for this test.

The getProtectedResourceMetadata function only reads from the config object passed to it, not from process.env.AUTH_SERVER. The save/restore logic for the env var is dead code.

♻️ Simplified test
 		test("builds protected-resource metadata from local server config", () => {
-			const previousAuthServer = process.env.AUTH_SERVER;
-			process.env.AUTH_SERVER = "auth.example.com";
-
 			const config = {
 				mcpServerUrl: "http://localhost:9292",
 				authServerIssuerUrl: "https://auth.example.com",
 			};

 			expect(getProtectedResourceMetadata(config)).toEqual({
 				resource: "http://localhost:9292/mcp",
 				authorization_servers: ["https://auth.example.com"],
 				scopes_supported: ["openid"],
 			});
-
-			if (previousAuthServer === undefined) {
-				delete process.env.AUTH_SERVER;
-			} else {
-				process.env.AUTH_SERVER = previousAuthServer;
-			}
 		});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server-http.test.ts` around lines 201 - 221, The test unnecessarily
manipulates process.env.AUTH_SERVER even though getProtectedResourceMetadata
reads only from the passed config; remove the env save/restore and the
assignment lines (the previousAuthServer capture, setting
process.env.AUTH_SERVER, and the conditional restore/delete) and keep the config
setup and expect assertion as-is so the test solely exercises
getProtectedResourceMetadata with the provided config.
src/server-http.ts (1)

174-183: Optional: Remove unused apiBaseUrl from the type signature.

Since the function no longer handles protected-resource paths, apiBaseUrl is unused but still required by the Pick type.

♻️ Suggested cleanup
 export function getWellKnownRedirectUrl(
 	path: string,
-	config: Pick<ServerConfig, "apiBaseUrl" | "authServerIssuerUrl">,
+	config: Pick<ServerConfig, "authServerIssuerUrl">,
 ): string | null {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server-http.ts` around lines 174 - 183, The function
getWellKnownRedirectUrl declares config as Pick<ServerConfig, "apiBaseUrl" |
"authServerIssuerUrl"> but no longer uses apiBaseUrl; update the type to only
require authServerIssuerUrl (e.g., Pick<ServerConfig, "authServerIssuerUrl"> or
a direct type with authServerIssuerUrl) so callers and the signature reflect the
actual dependency, and adjust any call sites if needed to stop passing
apiBaseUrl; keep the function body (and the reference to authServerIssuerUrl)
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/server-http.test.ts`:
- Around line 201-221: The test unnecessarily manipulates
process.env.AUTH_SERVER even though getProtectedResourceMetadata reads only from
the passed config; remove the env save/restore and the assignment lines (the
previousAuthServer capture, setting process.env.AUTH_SERVER, and the conditional
restore/delete) and keep the config setup and expect assertion as-is so the test
solely exercises getProtectedResourceMetadata with the provided config.

In `@src/server-http.ts`:
- Around line 174-183: The function getWellKnownRedirectUrl declares config as
Pick<ServerConfig, "apiBaseUrl" | "authServerIssuerUrl"> but no longer uses
apiBaseUrl; update the type to only require authServerIssuerUrl (e.g.,
Pick<ServerConfig, "authServerIssuerUrl"> or a direct type with
authServerIssuerUrl) so callers and the signature reflect the actual dependency,
and adjust any call sites if needed to stop passing apiBaseUrl; keep the
function body (and the reference to authServerIssuerUrl) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8cfd4db4-4fa6-4d2d-be76-8556ad87da07

📥 Commits

Reviewing files that changed from the base of the PR and between 217e929 and b781667.

📒 Files selected for processing (4)
  • src/auth/oauth-integration.test.ts
  • src/auth/oauth.test.ts
  • src/server-http.test.ts
  • src/server-http.ts

@mdthorpe-sc
mdthorpe-sc merged commit cfabb68 into main Mar 24, 2026
2 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant