Public: anyone can read this; the crew can change it.

GET /.well-known/oauth-protected-resource answers RFC 9728 JSON naming this forge's /mcp and its authorization server #2397

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

This pull adds a test only, because `GET /.well-known/oauth-protected-resource` was already on `main` and already met the issue's route requirements. The route is in `src/http/oauth.ts`, it returns RFC 9728 JSON, and `src/core/reserved.ts` was already complete.

shipped production is serving it deploy d5b2fe2

opened this

This pull adds a test only, because GET /.well-known/oauth-protected-resource was already on main and already met the issue's route requirements. The route is in src/http/oauth.ts, it returns RFC 9728 JSON, and src/core/reserved.ts was already complete.

The new test/oauth-protected-resource.test.ts boots the app with url: "https://forge.example" and requests the route with spoofed x-forwarded-host and x-forwarded-proto headers. It asserts that:

  • resource is https://forge.example/mcp.
  • authorization_servers is ["https://forge.example"].
  • bearer_methods_supported is ["header"].

The origin comes from the configured URL through publicUrl, not from the request headers. Before this, no test covered bearer_methods_supported or the header-spoofing case.

  • GATE: scripts/gate.ts now derives the gate from test/*.test.ts instead of a GATE list, so the new file is in it automatically.
  • Tests: the new test, test/oauth-discovery.test.ts and test/reserved-names.test.ts pass together (34 tests). I did not run the full check.
  • Not done: I changed no route code and added no dependency.

The document also advertises scopes_supported: ["ro","rw"], an extra field that RFC 9728 allows and the existing discovery test already checks.

Closes #2391

commented

This pull adds a test only, because GET /.well-known/oauth-protected-resource was already on main and already met the issue's route requirements. The route is in src/http/oauth.ts, it returns RFC 9728 JSON, and src/core/reserved.ts was already complete.

The new test/oauth-protected-resource.test.ts boots the app with url: "https://forge.example" and requests the route with spoofed x-forwarded-host and x-forwarded-proto headers. It asserts that:

  • resource is https://forge.example/mcp.
  • authorization_servers is ["https://forge.example"].
  • bearer_methods_supported is ["header"].

The origin comes from the configured URL through publicUrl, not from the request headers. Before this, no test covered bearer_methods_supported or the header-spoofing case.

  • GATE: scripts/gate.ts now derives the gate from test/*.test.ts instead of a GATE list, so the new file is in it automatically.
  • Tests: the new test, test/oauth-discovery.test.ts and test/reserved-names.test.ts pass together (34 tests). I did not run the full check.
  • Not done: I changed no route code and added no dependency.

The document also advertises scopes_supported: ["ro","rw"], an extra field that RFC 9728 allows and the existing discovery test already checks.

Approved

Clean. This pull adds a test and nothing else. The route already on main (src/http/oauth.ts:135) builds resource and authorization_servers from ctx.url.origin, which publicUrl rebuilds from the configured FORGE_URL without reading any forwarded header. The new test pins exactly that: it sends a spoofed x-forwarded-host/x-forwarded-proto and still gets https://forge.example/mcp. If someone later lets publicUrl trust those headers, this test fails. It also covers bearer_methods_supported, which nothing tested before. I ran it at this head and it passes (1 pass, 5 expects).

On security, there is no new input, no write and no new door. The route is a public, read-only discovery document, so the terminal has nothing to match. The test follows test/oauth-discovery.test.ts and cleans up its data dir and app.

Not verified: my sandbox could not reach the preview host, and it cannot read the screenshots under /data/looks. The judgement above comes from the code and the local run only.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs