@@ -14,24 +14,54 @@ namespace ProtectedMCPClient;
1414/// caching or any advanced token protection - it acquires a token and server metadata and holds it
1515/// in memory as-is. This is NOT PRODUCTION READY and MUST NOT BE USED IN PRODUCTION.
1616/// </summary>
17- /// <remarks>
18- /// Initializes a new instance of the <see cref="BasicOAuthAuthorizationProvider"/> class.
19- /// </remarks>
20- public class BasicOAuthAuthorizationProvider (
21- Uri serverUrl ,
22- string clientId = "demo-client" ,
23- string clientSecret = "" ,
24- Uri ? redirectUri = null ,
25- IEnumerable < string > ? scopes = null ) : IMcpAuthorizationProvider
17+ public class BasicOAuthAuthorizationProvider : ITokenProvider
2618{
27- private readonly Uri _serverUrl = serverUrl ?? throw new ArgumentNullException ( nameof ( serverUrl ) ) ;
28- private readonly Uri _redirectUri = redirectUri ?? new Uri ( "http://localhost:8080/callback" ) ;
29- private readonly List < string > _scopes = scopes ? . ToList ( ) ?? [ ] ;
30- private readonly HttpClient _httpClient = new ( ) ;
19+ private readonly Uri _serverUrl ;
20+ private readonly Uri _redirectUri ;
21+ private readonly List < string > _scopes ;
22+ private readonly string _clientId ;
23+ private readonly string _clientSecret ;
24+ private readonly HttpClient _httpClient ;
25+ private readonly AuthorizationHelpers _authorizationHelpers ;
26+
27+ // Client name for IHttpClientFactory used by the BasicOAuthAuthorizationProvider
28+ public const string HttpClientName = "ProtectedMCPClient.OAuth" ;
3129
3230 private TokenContainer ? _token ;
3331 private AuthorizationServerMetadata ? _authServerMetadata ;
3432
33+ /// <summary>
34+ /// Initializes a new instance of the <see cref="BasicOAuthAuthorizationProvider"/> class.
35+ /// </summary>
36+ /// <param name="serverUrl">The MCP server URL.</param>
37+ /// <param name="httpClientFactory">The HTTP client factory to use for creating HTTP clients.</param>
38+ /// <param name="authorizationHelpers">The authorization helpers.</param>
39+ /// <param name="clientId">OAuth client ID.</param>
40+ /// <param name="clientSecret">OAuth client secret.</param>
41+ /// <param name="redirectUri">OAuth redirect URI.</param>
42+ /// <param name="scopes">OAuth scopes.</param>
43+ public BasicOAuthAuthorizationProvider (
44+ Uri serverUrl ,
45+ IHttpClientFactory httpClientFactory ,
46+ AuthorizationHelpers authorizationHelpers ,
47+ string clientId = "demo-client" ,
48+ string clientSecret = "" ,
49+ Uri ? redirectUri = null ,
50+ IEnumerable < string > ? scopes = null )
51+ {
52+ _serverUrl = serverUrl ?? throw new ArgumentNullException ( nameof ( serverUrl ) ) ;
53+ if ( httpClientFactory == null ) throw new ArgumentNullException ( nameof ( httpClientFactory ) ) ;
54+ _authorizationHelpers = authorizationHelpers ?? throw new ArgumentNullException ( nameof ( authorizationHelpers ) ) ;
55+
56+ // Get the HttpClient once during construction instead of for each request
57+ _httpClient = httpClientFactory . CreateClient ( HttpClientName ) ;
58+
59+ _redirectUri = redirectUri ?? new Uri ( "http://localhost:8080/callback" ) ;
60+ _scopes = scopes ? . ToList ( ) ?? [ ] ;
61+ _clientId = clientId ;
62+ _clientSecret = clientSecret ;
63+ }
64+
3565 /// <inheritdoc />
3666 public IEnumerable < string > SupportedSchemes => new [ ] { "Bearer" } ;
3767
@@ -61,8 +91,8 @@ public class BasicOAuthAuthorizationProvider(
6191
6292 try
6393 {
64- // Get the metadata from the challenge
65- var resourceMetadata = await AuthorizationHelpers . ExtractProtectedResourceMetadata (
94+ // Get the metadata from the challenge using the instance-based AuthorizationHelpers
95+ var resourceMetadata = await _authorizationHelpers . ExtractProtectedResourceMetadata (
6696 response , _serverUrl , cancellationToken ) ;
6797
6898 if ( resourceMetadata ? . AuthorizationServers ? . Count > 0 )
@@ -152,7 +182,7 @@ public class BasicOAuthAuthorizationProvider(
152182 {
153183 [ "grant_type" ] = "refresh_token" ,
154184 [ "refresh_token" ] = refreshToken ,
155- [ "client_id" ] = clientId
185+ [ "client_id" ] = _clientId
156186 } ) ;
157187
158188 try
@@ -162,9 +192,9 @@ public class BasicOAuthAuthorizationProvider(
162192 Content = requestContent
163193 } ;
164194
165- if ( ! string . IsNullOrEmpty ( clientSecret ) )
195+ if ( ! string . IsNullOrEmpty ( _clientSecret ) )
166196 {
167- var authValue = Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( $ "{ clientId } :{ clientSecret } ") ) ;
197+ var authValue = Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( $ "{ _clientId } :{ _clientSecret } ") ) ;
168198 request . Headers . Authorization = new AuthenticationHeaderValue ( "Basic" , authValue ) ;
169199 }
170200
@@ -213,7 +243,7 @@ public class BasicOAuthAuthorizationProvider(
213243 private Uri BuildAuthorizationUrl ( AuthorizationServerMetadata authServerMetadata , string codeChallenge )
214244 {
215245 var queryParams = HttpUtility . ParseQueryString ( string . Empty ) ;
216- queryParams [ "client_id" ] = clientId ;
246+ queryParams [ "client_id" ] = _clientId ;
217247 queryParams [ "redirect_uri" ] = _redirectUri . ToString ( ) ;
218248 queryParams [ "response_type" ] = "code" ;
219249 queryParams [ "code_challenge" ] = codeChallenge ;
@@ -286,7 +316,7 @@ private Uri BuildAuthorizationUrl(AuthorizationServerMetadata authServerMetadata
286316 [ "grant_type" ] = "authorization_code" ,
287317 [ "code" ] = authorizationCode ,
288318 [ "redirect_uri" ] = _redirectUri . ToString ( ) ,
289- [ "client_id" ] = clientId ,
319+ [ "client_id" ] = _clientId ,
290320 [ "code_verifier" ] = codeVerifier
291321 } ) ;
292322
@@ -297,9 +327,9 @@ private Uri BuildAuthorizationUrl(AuthorizationServerMetadata authServerMetadata
297327 Content = requestContent
298328 } ;
299329
300- if ( ! string . IsNullOrEmpty ( clientSecret ) )
330+ if ( ! string . IsNullOrEmpty ( _clientSecret ) )
301331 {
302- var authValue = Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( $ "{ clientId } :{ clientSecret } ") ) ;
332+ var authValue = Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( $ "{ _clientId } :{ _clientSecret } ") ) ;
303333 request . Headers . Authorization = new AuthenticationHeaderValue ( "Basic" , authValue ) ;
304334 }
305335
0 commit comments