fix: correct well-known URL construction per RFC 9728

The .well-known/{suffix} segment was being appended to the full URL
path instead of inserted after the origin. For example:

  Wrong:   https://api.example.com/mcp/.well-known/oauth-protected-resource
  Correct: https://api.example.com/.well-known/oauth-protected-resource/mcp/

- Extract buildWellKnownUrl() helper in mcpTokenStore (Electron-free)
- Fix all 3 call sites: requiresOAuth probe, PRM discovery, auth
  server metadata
- Add 6 unit tests for URL construction with various path shapes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-27 19:46:25 +01:00
co-authored by Copilot
parent 1868a79d9a
commit d73eaae30b
3 changed files with 52 additions and 7 deletions
+4 -7
View File
@@ -5,7 +5,7 @@ import { shell } from 'electron';
import type { McpOauthStaticClientConfig } from '@shared/domain/mcpAuth';
import { storeToken, type McpOAuthToken } from './mcpTokenStore';
import { storeToken, buildWellKnownUrl, type McpOAuthToken } from './mcpTokenStore';
/* ── Public API ──────────────────────────────────────────────── */
@@ -39,8 +39,7 @@ export async function requiresOAuth(serverUrl: string): Promise<boolean> {
return false;
}
const base = serverUrl.replace(/\/+$/, '');
const prmUrl = `${base}/.well-known/oauth-protected-resource`;
const prmUrl = buildWellKnownUrl(serverUrl, 'oauth-protected-resource');
console.log(`[aryx oauth] Checking PRM at ${prmUrl}`);
const prmResponse = await fetch(prmUrl, {
signal: AbortSignal.timeout(5_000),
@@ -128,8 +127,7 @@ interface AuthServerMetadata {
}
async function discoverAuthorizationServer(serverUrl: string): Promise<string> {
const base = serverUrl.replace(/\/+$/, '');
const prmUrl = `${base}/.well-known/oauth-protected-resource`;
const prmUrl = buildWellKnownUrl(serverUrl, 'oauth-protected-resource');
const response = await fetch(prmUrl);
if (!response.ok) {
@@ -146,8 +144,7 @@ async function discoverAuthorizationServer(serverUrl: string): Promise<string> {
}
async function fetchAuthServerMetadata(authServerUrl: string): Promise<AuthServerMetadata> {
const base = authServerUrl.replace(/\/+$/, '');
const metadataUrl = `${base}/.well-known/oauth-authorization-server`;
const metadataUrl = buildWellKnownUrl(authServerUrl, 'oauth-authorization-server');
const response = await fetch(metadataUrl);
if (!response.ok) {