[v2] OAuth discovery validates any /.well-known/openid-configuration document as OIDC, rejecting conforming RFC 8414 metadata
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 58/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- typescript
- Área
- authentication, security
Línea de trabajo
Comienza con discoverAuthorizationServerMetadata() y los esquemas relacionados en client/dist/index.mjs; después, ejecuta la reproducción proporcionada de fetchFn contra el documento RFC 8414. Rastrea los fallos de los candidatos y la selección de esquemas, y verifica que se acepte un documento de metadatos OAuth conforme en /.well-known/openid-configuration o que el descubrimiento continúe con otro candidato, mientras la validación del issuer permanezca intacta.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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:
- RFC 8414 §5 explicitly permits that filename for general OAuth metadata. The server is conforming; the client is not.
- The parse throws instead of continuing the candidate loop. Every other failure in that loop (
continueon 4xx/502,continueon a CORS failure) falls through to the next candidate. A schema failure abortsdiscoverAuthorizationServerMetadata()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:
OpenIdProviderDiscoveryMetadataSchemais az.object(...), not az.looseObject(...)likeOAuthMetadataSchema. So a successful OIDC parse strips RFC 8414 fields that are not in the OIDC shape —revocation_endpointandintrospection_endpointamong them — from the returned metadata.- The doc comment on
discoverAuthorizationServerMetadatasays 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:
- try
OAuthMetadataSchemaand fall back toOpenIdProviderDiscoveryMetadataSchema(or vice versa) regardless of the candidate'stype—OAuthMetadataSchemais a loose object, so it accepts a full OIDC document without dropping any of its fields; or - treat a schema failure like the other per-candidate failures and
continueto 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])
- Lenguaje dominante
- TypeScript
- Estrellas
- 13.6k
- Forks
- 2.3k
- Merge medio
- 1 d 15 h
- PR fusionados (30 d)
- 51
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de modelcontextprotocol/typescript-sdk
-
Stateless 405 response omits the Allow headerPosiblemente ocupada @Hugo-DDT la tomó hace 1 día. Abiertov2
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
modelcontextprotocol/typescript-sdk#2970 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
[v2] @modelcontextprotocol/server inlines fast-uri 3.1.0, which has 9 published advisoriesPosiblemente ocupada @Andiii208 la tomó hace 3 días. Abiertov2
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
modelcontextprotocol/typescript-sdk#2966 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
v1 v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
modelcontextprotocol/typescript-sdk#2946 · 4 comentarios ·
Los mantenedores suelen responder en 1 día
-
[v2] URI template reserved expansions encode existing %HH sequences againPosiblemente ocupada @takagibit18 la tomó hace 10 días. Abiertov1 v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
modelcontextprotocol/typescript-sdk#2920 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
[v2] URI template strict expansions leave !'()* unencodedPosiblemente ocupada @takagibit18 la tomó hace 10 días. Abiertov1 v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
modelcontextprotocol/typescript-sdk#2919 · 1 comentario ·
Los mantenedores suelen responder en 1 día
Todos los issues de modelcontextprotocol/typescript-sdk
Issues similares
-
cleanName keeps a state code that's joined to the word before it (SavannahGa → "Savannah Ga")Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
openwatersio/slackwater-database#281 ·
Los mantenedores suelen responder en 1 día
-
accepted bug via-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
pingdotgg/t3code#18690 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Bayern feature:Application ready web
Dificultad 2/5 1-3 horas Aptitud para principiantes 67/100
digitalfabrik/entitlementcard#3176 ·
Los mantenedores suelen responder en 7 días
-
[BUG] 运行位置的分支列表不自动刷新,外部新建的分支看不到Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
NanmiCoder/cc-haha#1533 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día