Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/ModelContextProtocol.Core/Authentication/ClientOAuthOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ public sealed class ClientOAuthOptions
/// </remarks>
public AuthorizationRedirectDelegate? AuthorizationRedirectDelegate { get; set; }

/// <summary>
/// Gets or sets the token endpoint authentication method selector function.
/// </summary>
/// <remarks>
/// <para>
/// This function is used to select which token endpoint authentication method to use when multiple methods are available.
/// If not specified, the first available method will be selected.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
public Func<IReadOnlyList<string>?, string?>? TokenEndpointAuthMethodSelector { get; set; }

/// <summary>
/// Gets or sets the authorization server selector function.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ internal sealed partial class ClientOAuthProvider : McpHttpClient
private readonly Uri _redirectUri;
private readonly string? _configuredScopes;
private readonly IDictionary<string, string> _additionalAuthorizationParameters;
private readonly Func<IReadOnlyList<string>?, string?> _tokenEndpointAuthMethodSelector;
private readonly Func<IReadOnlyList<Uri>, Uri?> _authServerSelector;
private readonly AuthorizationRedirectDelegate _authorizationRedirectDelegate;
private readonly Uri? _clientMetadataDocumentUri;
Expand Down Expand Up @@ -79,6 +80,9 @@ public ClientOAuthProvider(
_additionalAuthorizationParameters = options.AdditionalAuthorizationParameters;
_clientMetadataDocumentUri = options.ClientMetadataDocumentUri;

// Set up token endpoint authentication method selector (use default if not provided)
_tokenEndpointAuthMethodSelector = options.TokenEndpointAuthMethodSelector ?? DefaultTokenEndpointAuthMethodSelector;

// Set up authorization server selection strategy
_authServerSelector = options.AuthServerSelector ?? DefaultAuthServerSelector;

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

/// <summary>
/// Default token endpoint authentication method selector that selects the first supported method from the authorization server metadata.
/// </summary>
/// <param name="tokenEndpointAuthMethodsSupported">The list of supported token endpoint authentication methods.</param>
/// <returns>The selected token endpoint authentication method, or null if none are available.</returns>
private static string? DefaultTokenEndpointAuthMethodSelector(IReadOnlyList<string>? tokenEndpointAuthMethodsSupported) => tokenEndpointAuthMethodsSupported?.FirstOrDefault();

/// <summary>
/// Default authorization server selection strategy that selects the first available server.
/// </summary>
Expand Down Expand Up @@ -306,7 +317,7 @@ await _tokenCache.GetTokensAsync(cancellationToken).ConfigureAwait(false) is { R
}

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

// Store auth server metadata for future refresh operations
_authServerMetadata = authServerMetadata;
Expand Down