From f4f45b516fe35de0307b446c8630a508308e44c3 Mon Sep 17 00:00:00 2001 From: Pierson Marks Date: Wed, 24 Jun 2026 17:17:46 -0700 Subject: [PATCH] fix(workos): serve OAuth AS metadata (CIMD/DCR) instead of OIDC discovery The /.well-known/oauth-authorization-server route mirrored AuthKit's OpenID Connect discovery document (/.well-known/openid-configuration), which omits client_id_metadata_document_supported (CIMD), registration_endpoint (DCR) and code_challenge_methods_supported (PKCE). AuthKit advertises those only at its RFC 8414 OAuth Authorization Server Metadata endpoint, so MCP clients (e.g. ChatGPT) reported CIMD/DCR as unsupported even when enabled in the dashboard. - Fetch /.well-known/oauth-authorization-server (RFC 8414) so the metadata carries the CIMD/DCR/PKCE fields. - Add a 5s AbortSignal.timeout on the upstream fetch. - Fall back to the static metadata on any fetch error instead of returning 500. --- packages/plugins/workos/src/provider.ts | 51 +++++++++++++++---------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/packages/plugins/workos/src/provider.ts b/packages/plugins/workos/src/provider.ts index 1706c6bab..03c6b76a6 100644 --- a/packages/plugins/workos/src/provider.ts +++ b/packages/plugins/workos/src/provider.ts @@ -66,34 +66,45 @@ function workosRouter(config: config): Router { router.get( "/.well-known/oauth-authorization-server", async (_req: Request, res: Response) => { + const authkitUrl = getAuthKitBaseUrl(config.authkitDomain); + try { - const authkitMetadataUrl = `${getAuthKitBaseUrl(config.authkitDomain)}/.well-known/openid-configuration`; - const response = await fetch(authkitMetadataUrl); + // RFC 8414 OAuth Authorization Server Metadata. AuthKit advertises the + // MCP-relevant fields ONLY here, not in the OIDC discovery document + // (/.well-known/openid-configuration): client_id_metadata_document_supported + // (CIMD), registration_endpoint (DCR) and code_challenge_methods_supported + // (PKCE). Mirroring the OIDC doc drops them, so clients (e.g. ChatGPT) + // report CIMD/DCR as unsupported even when enabled in the dashboard. + // The 5s timeout keeps a slow/stalled AuthKit from hanging the request. + const response = await fetch( + `${authkitUrl}/.well-known/oauth-authorization-server`, + { signal: AbortSignal.timeout(5000) } + ); if (response.ok) { - const data = await response.json(); - res.json(data); + res.json(await response.json()); return; } - - // Fallback - const authkitUrl = getAuthKitBaseUrl(config.authkitDomain); - const metadata: OAuthAuthorizationServerMetadata = { - issuer: authkitUrl, - authorization_endpoint: `${authkitUrl}/oauth2/authorize`, - token_endpoint: `${authkitUrl}/oauth2/token`, - jwks_uri: `${authkitUrl}/oauth2/jwks`, - response_types_supported: ["code"], - grant_types_supported: ["authorization_code", "refresh_token"], - code_challenge_methods_supported: ["S256"], - token_endpoint_auth_methods_supported: ["none", "client_secret_post"], - scopes_supported: ["openid", "profile", "email", "offline_access"], - }; - res.json(metadata); } catch (error) { console.error("[WorkOS] Failed to fetch OAuth metadata:", error); - res.status(500).json({ error: "Failed to get OAuth configuration" }); } + + // Static fallback, served when AuthKit's metadata endpoint is unreachable + // or errors. It intentionally omits CIMD/DCR: those depend on dashboard + // configuration the plugin cannot infer offline. Returning usable metadata + // is better than a 500, which would break discovery on a transient blip. + const metadata: OAuthAuthorizationServerMetadata = { + issuer: authkitUrl, + authorization_endpoint: `${authkitUrl}/oauth2/authorize`, + token_endpoint: `${authkitUrl}/oauth2/token`, + jwks_uri: `${authkitUrl}/oauth2/jwks`, + response_types_supported: ["code"], + grant_types_supported: ["authorization_code", "refresh_token"], + code_challenge_methods_supported: ["S256"], + token_endpoint_auth_methods_supported: ["none", "client_secret_post"], + scopes_supported: ["openid", "profile", "email", "offline_access"], + }; + res.json(metadata); } );