Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

Can't implement a CIMD client if auth provider doesn't put "none" first in it's list of supported token auth methods

Ouverte
#1,612 1 commentaire 1 réaction 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 2 jours

@mikeholczer y travaille déjà.

Depuis le 1/6/2026.

  • #1615 par @mikeholczer — ouverte
  • #1845 par @ump45nose — ouverte

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
62/100
Type d'issue
Bug
Clarté
Plutôt claire
Activité
Active
Stack technique
csharp

Piste de recherche

Commencez dans ClientOAuthProvider.GetAccessTokenAsync, ApplyClientIdMetadataDocument et CreateTokenRequest, puis suivez la manière dont DCR et les métadonnées du serveur définissent _tokenEndpointAuthMethod. Utilisez les tests before/after signalés comme point de départ et ajoutez une couverture pour CIMD avec none, en vérifiant la précédence explicit → DCR → server-advertised ainsi qu’une requête de token qui inclut client_id plutôt que des identifiants Basic.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

area-auth bug P2

Describe the bug

When authenticating as a public client identified by a Client ID Metadata Document (CIMD), ClientOAuthProvider can choose the wrong token-endpoint authentication method and the token exchange fails. This is the case when using Auth0 as an authentication provider.

The auth method is selected in GetAccessTokenAsync with:

_tokenEndpointAuthMethod ??= authServerMetadata.TokenEndpointAuthMethodsSupported?.FirstOrDefault();

Since it just takes the first method the authorization server advertises and ClientOAuthOptions exposes no way to override the method, if you don't have control over the authentication servers response, you can't get a token.

A CIMD client is a public client and must authenticate with none (proven via PKCE). But when the authorization server lists client_secret_basic ahead of none — as Auth0 does, advertising ["client_secret_basic","client_secret_post","private_key_jwt","none"], the provider picks client_secret_basic. CreateTokenRequest then sends the token request with an Authorization: Basic header built from the CIMD URL and an empty secret, and omits client_id from the body. A public/CIMD client has no client secret, so the authorization server rejects the exchange with 401 access_denied, and McpClient.CreateAsync throws.

Because the only place _tokenEndpointAuthMethod is set from client-specific data is the dynamic client registration (DCR) response, switching a working client from DCR to CIMD silently regresses the token-endpoint auth method.

To Reproduce
Steps to reproduce the behavior:

  1. Use an authorization server that supports CIMD (client_id_metadata_document_supported: true) and advertises client_secret_basic before none in token_endpoint_auth_methods_supported (e.g. Auth0).
  2. Host a CIMD document that declares "token_endpoint_auth_method": "none".
  3. Create a transport configured for CIMD only — no ClientId/ClientSecret, no DCR:
    await using var transport = new HttpClientTransport(new HttpClientTransportOptions
    {
        Endpoint = new Uri(mcpServerUrl),
        OAuth = new ClientOAuthOptions
        {
            RedirectUri = new Uri("https://localhost/auth/callback"),
            ClientMetadataDocumentUri = new Uri("https://example.com/client-metadata.json"),
            AuthorizationRedirectDelegate = HandleAuthorizationUrlAsync,
        },
    }, httpClient);
    
    await using var client = await McpClient.CreateAsync(transport);
    
  4. Complete the authorization-code flow. The authorize leg succeeds and returns a code, but the token-exchange POST /token is sent as Authorization: Basic base64(<cimd-url>:) with no client_id in the body.
  5. The authorization server responds 401 access_denied and CreateAsync throws.

Expected behavior
A CIMD public client should authenticate at the token endpoint with none (client id in the request body, PKCE as the proof of possession), matching the token_endpoint_auth_method declared in its metadata document, and the token exchange should succeed — regardless of which method the authorization server lists first. Pragmatically, it probably doesn't make sense for the client to read it's own CIMD, and the SDK should let the caller specify the token-endpoint authentication method.

Logs

End processing HTTP request after 126ms - 401   POST https://<issuer>/oauth/token
System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).
Response body: {"error":"access_denied","error_description":"Unauthorized"}
   at ModelContextProtocol.HttpResponseMessageExtensions.EnsureSuccessStatusCodeWithResponseBodyAsync(...)
   at ModelContextProtocol.Authentication.ClientOAuthProvider.ExchangeCodeForTokenAsync(...)
   at ModelContextProtocol.Authentication.ClientOAuthProvider.InitiateAuthorizationCodeFlowAsync(...)
   at ModelContextProtocol.Authentication.ClientOAuthProvider.GetAccessTokenAsync(...)

The corresponding token request omits client_id from the form body (it is Basic-encoded in the header with an empty secret), so the authorization server cannot identify the client.

Additional context

  • SDK version: 1.3.0 (also reproduces in 1.2.0 and on main — the TokenEndpointAuthMethodsSupported?.FirstOrDefault() selection and the CIMD handling are unchanged).
  • Root causes: (1) ApplyClientIdMetadataDocument discards the metadata document's token_endpoint_auth_method; (2) there is no option to set the token-endpoint auth method explicitly; so the provider falls back to the server's first-advertised method.
  • The confidential CIMD profile (private_key_jwt) is also not expressible — CreateTokenRequest only emits client_secret_basic, client_secret_post, or none — so none is the only CIMD profile the SDK can currently produce.

Proposed fix
Add an opt-in ClientOAuthOptions.TokenEndpointAuthMethod (used with precedence: explicit → DCR response → server-advertised first) and/or have ApplyClientIdMetadataDocument honor the document's declared method. I have a branch with the explicit-option fix plus before/after tests and am happy to open a PR.

Langage dominant
C#
Étoiles
4.6k
Forks
852
Merge moyen
9 j 3 h
PR mergées (30 j)
3

Préparer son environnement

Ouvrir dans Codespaces

Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de modelcontextprotocol/csharp-sdk

Toutes les issues de modelcontextprotocol/csharp-sdk

Issues similaires

Plus d'issues C#

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.