@@ -42,7 +42,9 @@ namespace RabbitMQ.Client.OAuth2
42
42
{
43
43
public class OAuth2ClientBuilder
44
44
{
45
- /// <summary>Discovery endpoint subpath for all OpenID Connect issuers.</summary>
45
+ /// <summary>
46
+ /// Discovery endpoint subpath for all OpenID Connect issuers.
47
+ /// </summary>
46
48
const string DISCOVERY_ENDPOINT = ".well-known/openid-configuration" ;
47
49
48
50
private readonly string _clientId ;
@@ -56,30 +58,53 @@ public class OAuth2ClientBuilder
56
58
private IDictionary < string , string > ? _additionalRequestParameters ;
57
59
private HttpClientHandler ? _httpClientHandler ;
58
60
61
+ /// <summary>
62
+ /// Create a new builder for creating <see cref="OAuth2Client"/>s.
63
+ /// </summary>
64
+ /// <param name="clientId">Id of the client</param>
65
+ /// <param name="clientSecret">Secret of the client</param>
66
+ /// <param name="tokenEndpoint">Endpoint to receive the Access Token</param>
67
+ /// <param name="issuer">Issuer of the Access Token. Used to automaticly receive the Token Endpoint while building</param>
68
+ /// <remarks>
69
+ /// Either <paramref name="tokenEndpoint"/> or <paramref name="issuer"/> must be provided.
70
+ /// </remarks>
59
71
public OAuth2ClientBuilder ( string clientId , string clientSecret , Uri ? tokenEndpoint = null , Uri ? issuer = null )
60
72
{
61
73
_clientId = clientId ?? throw new ArgumentNullException ( nameof ( clientId ) ) ;
62
74
_clientSecret = clientSecret ?? throw new ArgumentNullException ( nameof ( clientSecret ) ) ;
63
75
64
76
if ( tokenEndpoint is null && issuer is null )
65
- throw new ArgumentException ( "Either token endpoint or issuer is required" ) ;
77
+ throw new ArgumentException ( "Either tokenEndpoint or issuer is required" ) ;
66
78
67
79
_tokenEndpoint = tokenEndpoint ;
68
80
_issuer = issuer ;
69
81
}
70
82
83
+ /// <summary>
84
+ /// Set the requested scopes for the client.
85
+ /// </summary>
86
+ /// <param name="scope">OAuth scopes to request from the Issuer</param>
71
87
public OAuth2ClientBuilder SetScope ( string scope )
72
88
{
73
89
_scope = scope ?? throw new ArgumentNullException ( nameof ( scope ) ) ;
74
90
return this ;
75
91
}
76
92
93
+ /// <summary>
94
+ /// Set custom HTTP Client handler for requests of the OAuth2 client.
95
+ /// </summary>
96
+ /// <param name="handler">Custom handler for HTTP requests</param>
77
97
public OAuth2ClientBuilder SetHttpClientHandler ( HttpClientHandler handler )
78
98
{
79
99
_httpClientHandler = handler ?? throw new ArgumentNullException ( nameof ( handler ) ) ;
80
100
return this ;
81
101
}
82
102
103
+ /// <summary>
104
+ /// Add a additional request parameter to each HTTP request.
105
+ /// </summary>
106
+ /// <param name="param">Name of the parameter</param>
107
+ /// <param name="paramValue">Value of the parameter</param>
83
108
public OAuth2ClientBuilder AddRequestParameter ( string param , string paramValue )
84
109
{
85
110
if ( param is null )
@@ -98,8 +123,13 @@ public OAuth2ClientBuilder AddRequestParameter(string param, string paramValue)
98
123
return this ;
99
124
}
100
125
126
+ /// <summary>
127
+ /// Build the <see cref="OAuth2Client"/> with the provided properties of the builder.
128
+ /// </summary>
129
+ /// <returns>Configured OAuth2Client</returns>
101
130
public IOAuth2Client Build ( )
102
131
{
132
+ // Check if Token Endpoint is missing -> Use Issuer to receive Token Endpoint
103
133
if ( _tokenEndpoint is null )
104
134
{
105
135
// Don't know how to better handle backwards compatibily
@@ -111,8 +141,14 @@ public IOAuth2Client Build()
111
141
_scope , _additionalRequestParameters , _httpClientHandler ) ;
112
142
}
113
143
144
+ /// <summary>
145
+ /// Build the <see cref="OAuth2Client"/> with the provided properties of the builder.
146
+ /// </summary>
147
+ /// <param name="cancellationToken">Cancellation token for this method</param>
148
+ /// <returns>Configured OAuth2Client</returns>
114
149
public async ValueTask < IOAuth2Client > BuildAsync ( CancellationToken cancellationToken = default )
115
150
{
151
+ // Check if Token Endpoint is missing -> Use Issuer to receive Token Endpoint
116
152
if ( _tokenEndpoint is null )
117
153
{
118
154
Uri tokenEndpoint = await GetTokenEndpointFromIssuerAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
@@ -124,6 +160,11 @@ public async ValueTask<IOAuth2Client> BuildAsync(CancellationToken cancellationT
124
160
_scope , _additionalRequestParameters , _httpClientHandler ) ;
125
161
}
126
162
163
+ /// <summary>
164
+ /// Receive Token Endpoint from discovery page of the Issuer.
165
+ /// </summary>
166
+ /// <param name="cancellationToken">Cancellation token for this request</param>
167
+ /// <returns>Uri of the Token Endpoint</returns>
127
168
private async Task < Uri > GetTokenEndpointFromIssuerAsync ( CancellationToken cancellationToken = default )
128
169
{
129
170
if ( _issuer is null )
@@ -155,10 +196,8 @@ private async Task<Uri> GetTokenEndpointFromIssuerAsync(CancellationToken cancel
155
196
{
156
197
throw new InvalidOperationException ( "No token endpoint was found" ) ;
157
198
}
158
- else
159
- {
160
- return new Uri ( discovery . TokenEndpoint ) ;
161
- }
199
+
200
+ return new Uri ( discovery . TokenEndpoint ) ;
162
201
}
163
202
}
164
203
@@ -198,19 +237,15 @@ public OAuth2Client(string clientId, string clientSecret, Uri tokenEndpoint,
198
237
_additionalRequestParameters = additionalRequestParameters ?? EMPTY ;
199
238
_tokenEndpoint = tokenEndpoint ;
200
239
201
- if ( httpClientHandler is null )
202
- {
203
- _httpClient = new HttpClient ( ) ;
204
- }
205
- else
206
- {
207
- _httpClient = new HttpClient ( httpClientHandler , false ) ;
208
- }
240
+ _httpClient = httpClientHandler is null
241
+ ? new HttpClient ( )
242
+ : new HttpClient ( httpClientHandler , false ) ;
209
243
210
244
_httpClient . DefaultRequestHeaders . Accept . Clear ( ) ;
211
245
_httpClient . DefaultRequestHeaders . Accept . Add ( new MediaTypeWithQualityHeaderValue ( "application/json" ) ) ;
212
246
}
213
247
248
+ /// <inheritdoc />
214
249
public async Task < IToken > RequestTokenAsync ( CancellationToken cancellationToken = default )
215
250
{
216
251
using HttpRequestMessage req = new HttpRequestMessage ( HttpMethod . Post , _tokenEndpoint ) ;
@@ -229,12 +264,11 @@ public async Task<IToken> RequestTokenAsync(CancellationToken cancellationToken
229
264
// TODO specific exception?
230
265
throw new InvalidOperationException ( "token is null" ) ;
231
266
}
232
- else
233
- {
234
- return new Token ( token ) ;
235
- }
267
+
268
+ return new Token ( token ) ;
236
269
}
237
270
271
+ /// <inheritdoc />
238
272
public async Task < IToken > RefreshTokenAsync ( IToken token ,
239
273
CancellationToken cancellationToken = default )
240
274
{
@@ -259,10 +293,8 @@ public async Task<IToken> RefreshTokenAsync(IToken token,
259
293
// TODO specific exception?
260
294
throw new InvalidOperationException ( "refreshed token is null" ) ;
261
295
}
262
- else
263
- {
264
- return new Token ( refreshedToken ) ;
265
- }
296
+
297
+ return new Token ( refreshedToken ) ;
266
298
}
267
299
268
300
public void Dispose ( )
@@ -291,8 +323,7 @@ private Dictionary<string, string> BuildRequestParameters()
291
323
private Dictionary < string , string > BuildRefreshParameters ( IToken token )
292
324
{
293
325
Dictionary < string , string > dict = BuildRequestParameters ( ) ;
294
- dict . Remove ( GRANT_TYPE ) ;
295
- dict . Add ( GRANT_TYPE , REFRESH_TOKEN ) ;
326
+ dict [ GRANT_TYPE ] = REFRESH_TOKEN ;
296
327
297
328
if ( _scope != null )
298
329
{
@@ -349,6 +380,9 @@ public long ExpiresIn
349
380
}
350
381
}
351
382
383
+ /// <summary>
384
+ /// Minimal version of the properties of the discovery endpoint.
385
+ /// </summary>
352
386
internal class OpenIDConnectDiscovery
353
387
{
354
388
public OpenIDConnectDiscovery ( )
0 commit comments