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

Aberta
#2,733 1 comentário 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

@claude já está trabalhando nisso.

Desde 28/8/2026.

  • #2734 de @claude — aberto

Avaliação

Dificuldade
4/5
Tempo estimado
3-5 dias
Facilidade para iniciantes
58/100
Tipo de issue
Bug
Clareza
Razoavelmente clara
Status de atividade
Ativa
Stack de tecnologia
typescript

Direção de pesquisa

Comece com discoverAuthorizationServerMetadata() e os schemas relacionados em client/dist/index.mjs e, em seguida, execute a reprodução fornecida de fetchFn usando o documento RFC 8414. Rastreie as falhas dos candidatos e a seleção de schemas e verifique se um documento de metadados OAuth em conformidade em /.well-known/openid-configuration é aceito ou se a descoberta continua com outro candidato, mantendo intacta a validação do issuer.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

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])

Linguagem predominante
TypeScript
Estrelas
13.7k
Forks
2.3k
Merge médio
1d 12h
PRs com merge (30d)
44

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de modelcontextprotocol/typescript-sdk

Todas as issues de modelcontextprotocol/typescript-sdk

Issues semelhantes

Mais issues de TypeScript

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.