{"record":{"id":"f91f20a3e826c32d","repo":"zed-industries/zed","slug":"authorization-server-does-not-advertise-code-chall","errorCode":null,"errorMessage":"authorization server does not advertise code_challenge_methods_supported","messagePattern":"authorization server does not advertise code_challenge_methods_supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/context_server/src/oauth.rs","lineNumber":875,"sourceCode":"    http_client: &Arc<dyn HttpClient>,\n    server_url: &Url,\n    www_authenticate: &WwwAuthenticate,\n) -> Result<OAuthDiscovery> {\n    let resource_metadata =\n        fetch_protected_resource_metadata(http_client, server_url, www_authenticate).await?;\n\n    let auth_server_url = resource_metadata\n        .authorization_servers\n        .first()\n        .ok_or_else(|| anyhow!(\"no authorization servers in resource metadata\"))?;\n\n    let auth_server_metadata = fetch_auth_server_metadata(http_client, auth_server_url).await?;\n\n    // Verify PKCE S256 support (spec requirement).\n    match &auth_server_metadata.code_challenge_methods_supported {\n        Some(methods) if methods.iter().any(|m| m == \"S256\") => {}\n        Some(_) => bail!(\"authorization server does not support S256 PKCE\"),\n        None => bail!(\"authorization server does not advertise code_challenge_methods_supported\"),\n    }\n\n    let scopes = select_scopes(www_authenticate, &resource_metadata);\n\n    Ok(OAuthDiscovery {\n        resource_metadata,\n        auth_server_metadata,\n        scopes,\n    })\n}\n\n/// Resolve the OAuth client registration for an authorization flow.\n///\n/// CIMD uses the static client metadata document directly. For DCR, a fresh\n/// registration is performed each time because the loopback redirect URI\n/// includes an ephemeral port that changes every flow.\npub async fn resolve_client_registration(\n    http_client: &Arc<dyn HttpClient>,","sourceCodeStart":857,"sourceCodeEnd":893,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/context_server/src/oauth.rs#L857-L893","documentation":"Sister check to error 170: discover() requires the auth server metadata to include the code_challenge_methods_supported field at all. When the field is absent (None after deserialization), the client refuses to proceed even though the OAuth discovery response is otherwise fine, because it cannot confirm S256 PKCE support as the MCP spec requires. Note this is stricter than plain OAuth2, where a missing field conventionally implies 'plain' only.","triggerScenarios":"Auth server metadata JSON omits code_challenge_methods_supported entirely (the field is Option in AuthServerMetadataResponse), so discover() hits the None => bail! arm.","commonSituations":"Standard OIDC providers that don't include the (RFC 8414 / draft) PKCE methods field in their discovery document; minimal or hand-rolled authorization servers that implemented the required OAuth fields but skipped PKCE advertisement; older server versions predating the MCP authorization spec.","solutions":["Update or configure the authorization server so its metadata document advertises \"code_challenge_methods_supported\": [\"S256\"]","If using a proxy/gateway in front of the auth server, have it inject the field into the served discovery document","Upgrade the auth server to a version whose discovery document includes PKCE support advertisement"],"exampleFix":"// before (discovery document lacks the field)\n{ \"issuer\": \"https://auth.example.com\", \"authorization_endpoint\": \"...\" }\n\n// after\n{ \"issuer\": \"https://auth.example.com\", \"authorization_endpoint\": \"...\",\n  \"code_challenge_methods_supported\": [\"S256\"] }","handlingStrategy":"validation","validationCode":"// client-side: treat an absent field as a hard precondition\nanyhow::ensure!(\n    metadata.get(\"code_challenge_methods_supported\").is_some(),\n    \"auth server metadata must include code_challenge_methods_supported (MCP requires S256 PKCE)\"\n);","typeGuard":"fn advertises_pkce_methods(doc: &serde_json::Value) -> bool {\n    doc.get(\"code_challenge_methods_supported\").is_some()\n}","tryCatchPattern":"match discover(&client, &server_url, &challenge).await {\n    Err(err) if err.to_string().contains(\"does not advertise code_challenge_methods_supported\") => {\n        // add the field server-side; no client-side workaround exists\n        report_server_requirement(\"add code_challenge_methods_supported to the discovery document\");\n        Err(err)\n    }\n    other => other,\n}","preventionTips":["Never omit code_challenge_methods_supported in metadata meant for MCP clients","If you proxy the discovery document, inject the field rather than passing through an older provider response","Validate the full MCP-required field set in your metadata deployment pipeline"],"tags":["oauth","mcp","pkce","metadata","spec-compliance"],"backgroundTag":"oauth-pkce-s256-unsupported","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}