Skip to content

Commit e6c95ea

Browse files
committed
Added configurable token endpoint auth method selection
The OAuth client currently selects the first token endpoint authentication method advertised by the authorization server. That can fail when servers expose multiple supported methods and the caller needs to prefer a different option based on client type or credentials. Added TokenEndpointAuthMethodSelector to ClientOAuthOptions and use it in ClientOAuthProvider when resolving the token endpoint auth method. Preserve the existing behavior by defaulting to the first advertised method when no selector is provided.
1 parent 1492a5d commit e6c95ea

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/ModelContextProtocol.Core/Authentication/ClientOAuthOptions.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,20 @@ public sealed class ClientOAuthOptions
6363
/// </remarks>
6464
public AuthorizationRedirectDelegate? AuthorizationRedirectDelegate { get; set; }
6565

66+
/// <summary>
67+
/// Gets or sets the token endpoint authentication method selector function.
68+
/// </summary>
69+
/// <remarks>
70+
/// <para>
71+
/// This function is used to select which token endpoint authentication method to use when multiple methods are available.
72+
/// If not specified, the first available method will be selected.
73+
/// </para>
74+
/// <para>
75+
/// The function receives a list of supported authentication methods from the authorization server metadata and should return the selected method, or null if no suitable method is found.
76+
/// </para>
77+
/// </remarks>
78+
public Func<IReadOnlyList<string>?, string?>? TokenEndpointAuthMethodSelector { get; set; }
79+
6680
/// <summary>
6781
/// Gets or sets the authorization server selector function.
6882
/// </summary>

src/ModelContextProtocol.Core/Authentication/ClientOAuthProvider.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ internal sealed partial class ClientOAuthProvider : McpHttpClient
2929
private readonly Uri _redirectUri;
3030
private readonly string? _configuredScopes;
3131
private readonly IDictionary<string, string> _additionalAuthorizationParameters;
32+
private readonly Func<IReadOnlyList<string>?, string?> _tokenEndpointAuthMethodSelector;
3233
private readonly Func<IReadOnlyList<Uri>, Uri?> _authServerSelector;
3334
private readonly AuthorizationRedirectDelegate _authorizationRedirectDelegate;
3435
private readonly Uri? _clientMetadataDocumentUri;
@@ -79,6 +80,9 @@ public ClientOAuthProvider(
7980
_additionalAuthorizationParameters = options.AdditionalAuthorizationParameters;
8081
_clientMetadataDocumentUri = options.ClientMetadataDocumentUri;
8182

83+
// Set up token endpoint authentication method selector (use default if not provided)
84+
_tokenEndpointAuthMethodSelector = options.TokenEndpointAuthMethodSelector ?? DefaultTokenEndpointAuthMethodSelector;
85+
8286
// Set up authorization server selection strategy
8387
_authServerSelector = options.AuthServerSelector ?? DefaultAuthServerSelector;
8488

@@ -92,6 +96,13 @@ public ClientOAuthProvider(
9296
_tokenCache = options.TokenCache ?? new InMemoryTokenCache();
9397
}
9498

99+
/// <summary>
100+
/// Default token endpoint authentication method selector that selects the first supported method from the authorization server metadata.
101+
/// </summary>
102+
/// <param name="tokenEndpointAuthMethodsSupported">The list of supported token endpoint authentication methods.</param>
103+
/// <returns>The selected token endpoint authentication method, or null if none are available.</returns>
104+
private static string? DefaultTokenEndpointAuthMethodSelector(IReadOnlyList<string>? tokenEndpointAuthMethodsSupported) => tokenEndpointAuthMethodsSupported?.FirstOrDefault();
105+
95106
/// <summary>
96107
/// Default authorization server selection strategy that selects the first available server.
97108
/// </summary>
@@ -306,7 +317,7 @@ await _tokenCache.GetTokensAsync(cancellationToken).ConfigureAwait(false) is { R
306317
}
307318

308319
// Determine the token endpoint auth method from server metadata if not already set by DCR.
309-
_tokenEndpointAuthMethod ??= authServerMetadata.TokenEndpointAuthMethodsSupported?.FirstOrDefault();
320+
_tokenEndpointAuthMethod ??= _tokenEndpointAuthMethodSelector(authServerMetadata.TokenEndpointAuthMethodsSupported);
310321

311322
// Store auth server metadata for future refresh operations
312323
_authServerMetadata = authServerMetadata;

0 commit comments

Comments
 (0)