Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[v2] OAuth discovery validates any /.well-known/openid-configuration document as OIDC, rejecting conforming RFC 8414 metadata

オープン
#2,733 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@claude がすでに取り組んでいます。

2026年8月28日 から。

  • #2734 @claude による — オープン

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
58/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
typescript

調査の方向性

まず client/dist/index.mjs の discoverAuthorizationServerMetadata() と関連するスキーマから始め、次に提供された fetchFn の再現を RFC 8414 ドキュメントに対して実行します。候補の失敗とスキーマ選択を追跡し、適合する OAuth メタデータドキュメントが /.well-known/openid-configuration で受け入れられるか、または issuer の検証を維持したまま別の候補へ discovery が継続されることを確認します。

索引モデルが issue の本文から書いたものです。

説明

v1 v2
What happened?

discoverAuthorizationServerMetadata() picks its validation schema from which well-known filename resolved, not from the document that came back. Every openid-configuration candidate is typed "oidc", so anything served there is validated against OpenIdProviderDiscoveryMetadataSchema:

// client/dist/index.mjs (2.0.0)
const parsed = type === "oauth"
  ? OAuthMetadataSchema.parse(await response.json())
  : OpenIdProviderDiscoveryMetadataSchema.parse(await response.json());

That schema requires jwks_uri, subject_types_supported and id_token_signing_alg_values_supported — three fields OpenID Connect Discovery 1.0 requires and RFC 8414 does not. So a plain OAuth 2.0 authorization server (no ID tokens, no JWKS, no sub) that publishes RFC 8414 metadata at /.well-known/openid-configuration is rejected:

[
  {"expected":"string","code":"invalid_type","path":["jwks_uri"],"message":"Invalid input: expected string, received undefined"},
  {"expected":"array","code":"invalid_type","path":["subject_types_supported"],"message":"Invalid input: expected array, received undefined"},
  {"expected":"array","code":"invalid_type","path":["id_token_signing_alg_values_supported"],"message":"Invalid input: expected array, received undefined"}
]

Two things make this fatal rather than cosmetic:

  1. RFC 8414 §5 explicitly permits that filename for general OAuth metadata. The server is conforming; the client is not.
  2. The parse throws instead of continuing the candidate loop. Every other failure in that loop (continue on 4xx/502, continue on a CORS failure) falls through to the next candidate. A schema failure aborts discoverAuthorizationServerMetadata() entirely, so no later candidate is tried and the whole connection fails.

Reported downstream at modelcontextprotocol/inspector#2172 against a real server (https://misc.poodll.com/mod/minilesson/mcp.php, a plain OAuth 2.0 AS whose resource lives under a path). Reproduced independently against @modelcontextprotocol/[email protected] with an injected fetchFn, and again against a local test server that serves RFC 8414 metadata only at /.well-known/openid-configuration.

Two smaller things noticed in the same code path, mentioned here rather than as separate issues since a fix will likely touch both:

  • OpenIdProviderDiscoveryMetadataSchema is a z.object(...), not a z.looseObject(...) like OAuthMetadataSchema. So a successful OIDC parse strips RFC 8414 fields that are not in the OIDC shape — revocation_endpoint and introspection_endpoint among them — from the returned metadata.
  • The doc comment on discoverAuthorizationServerMetadata says it "attempts RFC 8414 OAuth metadata discovery first / if OAuth discovery fails, falls back to OpenID Connect Discovery", which is what the URL ordering does but not what the schema selection does.
What did you expect?

A document should be validated by what it is, not by the filename it was found under. Concretely, either:

  1. try OAuthMetadataSchema and fall back to OpenIdProviderDiscoveryMetadataSchema (or vice versa) regardless of the candidate's type — OAuthMetadataSchema is a loose object, so it accepts a full OIDC document without dropping any of its fields; or
  2. treat a schema failure like the other per-candidate failures and continue to the next candidate rather than throwing out of the whole function.

Either way, issuer validation (RFC 8414 §3.3 / OIDC Discovery §4.3) should stay exactly as it is.

Code to reproduce
import { discoverAuthorizationServerMetadata } from '@modelcontextprotocol/client';

// A plain OAuth 2.0 AS: RFC 8414 metadata, served only at the OIDC well-known path.
const METADATA = {
    issuer: 'https://as.example.com',
    authorization_endpoint: 'https://as.example.com/oauth/authorize',
    token_endpoint: 'https://as.example.com/oauth/token',
    response_types_supported: ['code'],
    grant_types_supported: ['authorization_code', 'refresh_token'],
    code_challenge_methods_supported: ['S256'],
};

const fetchFn: typeof fetch = async input => {
    const url = String(input);
    if (url === 'https://as.example.com/.well-known/openid-configuration') {
        return new Response(JSON.stringify(METADATA), {
            status: 200,
            headers: { 'content-type': 'application/json' },
        });
    }
    return new Response('not found', { status: 404 });
};

// Throws a ZodError for jwks_uri / subject_types_supported /
// id_token_signing_alg_values_supported. Expected: the RFC 8414 document.
await discoverAuthorizationServerMetadata('https://as.example.com', { fetchFn });
SDK version

@modelcontextprotocol/[email protected] (with @modelcontextprotocol/[email protected])

主要言語
TypeScript
スター
13.5k
フォーク
2.3k
平均マージ
1日 22時間
マージ済み PR(30日)
52

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

modelcontextprotocol/typescript-sdk のほかの issue

modelcontextprotocol/typescript-sdk の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。