diff --git a/src/client/auth.test.ts b/src/client/auth.test.ts index 1b9fb071..1cb4c41f 100644 --- a/src/client/auth.test.ts +++ b/src/client/auth.test.ts @@ -206,6 +206,20 @@ describe("OAuth Authorization", () => { }); }); + it("returns metadata when discovery succeeds", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => validMetadata, + }); + + await discoverOAuthMetadata("https://auth.example.com", {useOidcConfig: true}); + const calls = mockFetch.mock.calls; + expect(calls.length).toBe(1); + const [url] = calls[0]; + expect(url.toString()).toBe("https://auth.example.com/.well-known/openid-configuration"); + }); + it("returns metadata when first fetch fails but second without MCP header succeeds", async () => { // Set up a counter to control behavior let callCount = 0; diff --git a/src/client/auth.ts b/src/client/auth.ts index 7a91eb25..d09d62fe 100644 --- a/src/client/auth.ts +++ b/src/client/auth.ts @@ -71,6 +71,13 @@ export interface OAuthClientProvider { * the authorization result. */ codeVerifier(): string | Promise; + + /** + * Use OpenID Provider configuration information for authorization + * server metadata. + * https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig + */ + useOidcProviderConfiguration?(): boolean | Promise; } export type AuthResult = "AUTHORIZED" | "REDIRECT"; @@ -111,7 +118,9 @@ export async function auth( console.warn("Could not load OAuth Protected Resource metadata, falling back to /.well-known/oauth-authorization-server", error) } - const metadata = await discoverOAuthMetadata(authorizationServerUrl); + const metadata = await discoverOAuthMetadata(authorizationServerUrl, { + useOidcConfig: await provider.useOidcProviderConfiguration?.() + }); // Handle client registration if needed let clientInformation = await Promise.resolve(provider.clientInformation()); @@ -267,9 +276,15 @@ export async function discoverOAuthProtectedResourceMetadata( */ export async function discoverOAuthMetadata( authorizationServerUrl: string | URL, - opts?: { protocolVersion?: string }, + opts?: { + protocolVersion?: string + useOidcConfig?: boolean + }, ): Promise { - const url = new URL("/.well-known/oauth-authorization-server", authorizationServerUrl); + const metadataPath = opts?.useOidcConfig ? + "openid-configuration" : + "oauth-authorization-server"; + const url = new URL(`/.well-known/${metadataPath}`, authorizationServerUrl); let response: Response; try { response = await fetch(url, {