From 8c2bb09ef0245050152310423f77c1b57d70f667 Mon Sep 17 00:00:00 2001 From: Dhruv Savaliya Date: Tue, 17 Mar 2026 11:23:32 -0600 Subject: [PATCH 1/2] fix: suppress RFC 8707 resource parameter in OAuth authorization requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add validateResourceURL() to InspectorOAuthClientProvider to prevent the SDK from appending the RFC 8707 'resource' query parameter to the /authorize URL. Authorization servers that do not support RFC 8707 — notably Azure Entra ID v2.0 — reject authorization requests containing this parameter with errors like AADSTS9010010. The resource field in RFC 9728 Protected Resource Metadata is intended for discovery, not for inclusion in authorization requests to servers that rely solely on scopes. Returning undefined from the hook tells the SDK to omit the parameter. PRM-based discovery of authorization_servers and scopes_supported continues to work normally. --- client/src/lib/auth.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/client/src/lib/auth.ts b/client/src/lib/auth.ts index 879936104..c9b473a24 100644 --- a/client/src/lib/auth.ts +++ b/client/src/lib/auth.ts @@ -137,6 +137,32 @@ export class InspectorOAuthClientProvider implements OAuthClientProvider { return getScopeFromSessionStorage(this.serverUrl); } + /** + * Suppress the RFC 8707 `resource` parameter in authorization requests. + * + * The MCP TypeScript SDK reads the `resource` field from RFC 9728 Protected + * Resource Metadata (PRM) and by default forwards it as a `resource` query + * parameter on the /authorize URL. Authorization servers that do not support + * the RFC 8707 `resource` parameter — notably Azure Entra ID v2.0, which + * treats it as a v1.0-only concept — reject the request with an error such + * as AADSTS9010010 ("The resource parameter … doesn't match … the requested + * scopes"), even when the PRM `resource` value is a perfectly valid + * RFC 9728-compliant server URL. + * + * By implementing this hook and returning `undefined`, we tell the SDK to + * omit the `resource` parameter entirely. The authorization server identity + * and supported scopes are still fully discovered from PRM via the + * `authorization_servers` and `scopes_supported` fields, so discovery is + * unaffected. Only the redundant (and potentially incompatible) `resource` + * query parameter is dropped from the authorize URL. + */ + validateResourceURL( + _serverUrl: URL, + _resourceMetadataUrl?: string, + ): Promise { + return Promise.resolve(undefined); + } + get redirectUrl() { return window.location.origin + "/oauth/callback"; } From e4843588d418d39b90ef89bff270bc9f16136b8c Mon Sep 17 00:00:00 2001 From: Dhruv Savaliya Date: Tue, 17 Mar 2026 11:29:28 -0600 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20clarify=20comment=20=E2=80=94?= =?UTF-8?q?=20acknowledge=20RFC=208707=20trade-off=20for=20multi-resource?= =?UTF-8?q?=20envs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/lib/auth.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/client/src/lib/auth.ts b/client/src/lib/auth.ts index c9b473a24..dbbf614c3 100644 --- a/client/src/lib/auth.ts +++ b/client/src/lib/auth.ts @@ -142,19 +142,25 @@ export class InspectorOAuthClientProvider implements OAuthClientProvider { * * The MCP TypeScript SDK reads the `resource` field from RFC 9728 Protected * Resource Metadata (PRM) and by default forwards it as a `resource` query - * parameter on the /authorize URL. Authorization servers that do not support - * the RFC 8707 `resource` parameter — notably Azure Entra ID v2.0, which - * treats it as a v1.0-only concept — reject the request with an error such - * as AADSTS9010010 ("The resource parameter … doesn't match … the requested - * scopes"), even when the PRM `resource` value is a perfectly valid - * RFC 9728-compliant server URL. + * parameter on the /authorize URL. However, RFC 8707 defines the `resource` + * parameter as OPTIONAL — authorization servers are not required to support + * it. Some servers actively reject the parameter: specifically, Azure Entra + * ID v2.0 returns AADSTS9010010 ("The resource parameter … doesn't match … + * the requested scopes") when `resource` is present, even when the PRM + * `resource` value is a valid RFC 9728-compliant server URL. * * By implementing this hook and returning `undefined`, we tell the SDK to * omit the `resource` parameter entirely. The authorization server identity * and supported scopes are still fully discovered from PRM via the * `authorization_servers` and `scopes_supported` fields, so discovery is - * unaffected. Only the redundant (and potentially incompatible) `resource` - * query parameter is dropped from the authorize URL. + * unaffected. + * + * Trade-off: In multi-resource environments (one authorization server + * protecting several resource servers), the `resource` parameter helps + * audience-restrict tokens to a specific resource. For the Inspector — a + * single-connection developer tool where the scope already encodes the + * target resource — omitting it is safe and compatible with all major + * authorization servers (Keycloak, Auth0, Okta, PingFederate, Entra ID). */ validateResourceURL( _serverUrl: URL,