diff --git a/client/src/lib/auth.ts b/client/src/lib/auth.ts index 7012c782..35551296 100644 --- a/client/src/lib/auth.ts +++ b/client/src/lib/auth.ts @@ -205,10 +205,35 @@ export class DebugInspectorOAuthClientProvider extends InspectorOAuthClientProvi return JSON.parse(metadata); } + /** + * Saves the resource URL to session storage to persist it across the redirect. + */ + saveResource(resource: URL): void { + const key = getServerSpecificKey(SESSION_KEYS.RESOURCE_URL, this.serverUrl); + sessionStorage.setItem(key, resource.toString()); + } + + /** + * Retrieves the persisted resource URL from session storage. + */ + getResource(): URL | undefined { + const key = getServerSpecificKey(SESSION_KEYS.RESOURCE_URL, this.serverUrl); + const urlString = sessionStorage.getItem(key); + if (!urlString) { + return undefined; + } + return new URL(urlString); + } + clear() { super.clear(); sessionStorage.removeItem( getServerSpecificKey(SESSION_KEYS.SERVER_METADATA, this.serverUrl), ); + + // Also clear the resource URL + sessionStorage.removeItem( + getServerSpecificKey(SESSION_KEYS.RESOURCE_URL, this.serverUrl), + ); } } diff --git a/client/src/lib/constants.ts b/client/src/lib/constants.ts index 2e983302..bf2dc599 100644 --- a/client/src/lib/constants.ts +++ b/client/src/lib/constants.ts @@ -9,6 +9,7 @@ export const SESSION_KEYS = { PREREGISTERED_CLIENT_INFORMATION: "mcp_preregistered_client_information", SERVER_METADATA: "mcp_server_metadata", AUTH_DEBUGGER_STATE: "mcp_auth_debugger_state", + RESOURCE_URL: "mcp_resource_url", } as const; // Generate server-specific session storage keys diff --git a/client/src/lib/oauth-state-machine.ts b/client/src/lib/oauth-state-machine.ts index 24b62084..c58dacb3 100644 --- a/client/src/lib/oauth-state-machine.ts +++ b/client/src/lib/oauth-state-machine.ts @@ -57,6 +57,11 @@ export const oauthTransitions: Record = { resourceMetadata ?? undefined, ); + // Persist the resource URL so it survives the redirect. + if (resource) { + context.provider.saveResource(resource); + } + const metadata = await discoverAuthorizationServerMetadata(authServerUrl); if (!metadata) { throw new Error("Failed to discover OAuth metadata"); @@ -171,13 +176,16 @@ export const oauthTransitions: Record = { const metadata = context.provider.getServerMetadata()!; const clientInformation = (await context.provider.clientInformation())!; + // Retrieve the resource from persistent storage, not volatile state. + const resource = context.provider.getResource(); + const tokens = await exchangeAuthorization(context.serverUrl, { metadata, clientInformation, authorizationCode: context.state.authorizationCode, codeVerifier, redirectUri: context.provider.redirectUrl, - resource: context.state.resource ?? undefined, + resource: resource ?? undefined, }); context.provider.saveTokens(tokens);