Skip to content

Commit de102ec

Browse files
committed
Refactor class files
1 parent 86f28d0 commit de102ec

20 files changed

+350
-303
lines changed

Patros.AuthenticatedHttpClient.AuthorizationHeader/AuthorizationHeaderAuthenticatedHttpClient.cs

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,7 @@
1-
using System;
2-
using System.Net.Http;
3-
using System.Net.Http.Headers;
4-
using System.Threading;
5-
using System.Threading.Tasks;
1+
using System.Net.Http;
62

73
namespace Patros.AuthenticatedHttpClient
84
{
9-
public class AuthorizationHeaderAuthenticatedHttpClientOptions
10-
{
11-
public string Value;
12-
}
13-
14-
public class AuthorizationHeaderAuthenticatedHttpMessageHandler : DelegatingHandler
15-
{
16-
private AuthenticationHeaderValue _authorizationHeader;
17-
18-
public AuthorizationHeaderAuthenticatedHttpMessageHandler(AuthorizationHeaderAuthenticatedHttpClientOptions options, HttpMessageHandler innerHandler = null)
19-
{
20-
InnerHandler = innerHandler ?? new HttpClientHandler();
21-
22-
_authorizationHeader = new AuthenticationHeaderValue(options.Value);
23-
}
24-
25-
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
26-
{
27-
request.Headers.Authorization = _authorizationHeader;
28-
return await base.SendAsync(request, cancellationToken);
29-
}
30-
}
31-
325
public static class AuthorizationHeaderAuthenticatedHttpClient
336
{
347
public static HttpClient GetClient(AuthorizationHeaderAuthenticatedHttpClientOptions options, HttpMessageHandler innerHandler = null)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Patros.AuthenticatedHttpClient
2+
{
3+
public class AuthorizationHeaderAuthenticatedHttpClientOptions
4+
{
5+
public string Value;
6+
}
7+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Net.Http;
2+
using System.Net.Http.Headers;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
6+
namespace Patros.AuthenticatedHttpClient
7+
{
8+
public class AuthorizationHeaderAuthenticatedHttpMessageHandler : DelegatingHandler
9+
{
10+
private AuthenticationHeaderValue _authorizationHeader;
11+
12+
public AuthorizationHeaderAuthenticatedHttpMessageHandler(AuthorizationHeaderAuthenticatedHttpClientOptions options, HttpMessageHandler innerHandler = null)
13+
{
14+
InnerHandler = innerHandler ?? new HttpClientHandler();
15+
16+
_authorizationHeader = new AuthenticationHeaderValue(options.Value);
17+
}
18+
19+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
20+
{
21+
request.Headers.Authorization = _authorizationHeader;
22+
return await base.SendAsync(request, cancellationToken);
23+
}
24+
}
25+
}

Patros.AuthenticatedHttpClient.AzureAd/AzureAdAuthenticatedHttpClient.cs

Lines changed: 1 addition & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,9 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Net.Http;
4-
using System.Net.Http.Headers;
5-
using System.Globalization;
6-
using System.Threading;
7-
using System.Threading.Tasks;
8-
using System.Configuration;
9-
using Microsoft.IdentityModel.Clients.ActiveDirectory;
1+
using System.Net.Http;
102

113
namespace Patros.AuthenticatedHttpClient
124
{
135
// implementation shamelessly ripped off from the Azure sample
146
// https://github.com/Azure-Samples/active-directory-dotnet-daemon/blob/master/TodoListDaemon/Program.cs
15-
public class AzureAdAuthenticatedHttpClientOptions {
16-
/// <summary>
17-
/// The AAD Instance is the instance of Azure, for example public Azure or Azure China.
18-
/// </summary>
19-
/// <value></value>
20-
public string AadInstance { get; set; } = "https://login.microsoftonline.com/{0}";
21-
22-
/// <summary>
23-
/// The Tenant is the name of the Azure AD tenant in which this application is registered.
24-
/// </summary>
25-
/// <value></value>
26-
public string Tenant { get; set; }
27-
28-
/// <summary>
29-
/// The Client ID is used by the application to uniquely identify itself to Azure AD.
30-
/// </summary>
31-
/// <value></value>
32-
public string ClientId { get; set; }
33-
34-
/// <summary>
35-
/// The App Key is a credential used by the application to authenticate to Azure AD.
36-
/// </summary>
37-
/// <value></value>
38-
public string AppKey { get; set; }
39-
40-
/// <summary>
41-
/// The Resource Id is the id of the service you are contacting/authenticating to.
42-
/// </summary>
43-
/// <value></value>
44-
public string ResourceId { get; set; }
45-
}
46-
47-
public class AzureAdAuthenticatedHttpMessageHandler : DelegatingHandler
48-
{
49-
private string _resourceId;
50-
private AuthenticationContext _authContext;
51-
private ClientCredential _clientCredential;
52-
53-
public AzureAdAuthenticatedHttpMessageHandler(AzureAdAuthenticatedHttpClientOptions options, HttpMessageHandler innerHandler = null)
54-
{
55-
InnerHandler = innerHandler ?? new HttpClientHandler();
56-
57-
_resourceId = options.ResourceId;
58-
59-
var authority = String.Format(CultureInfo.InvariantCulture, options.AadInstance, options.Tenant);
60-
_authContext = new AuthenticationContext(authority);
61-
62-
_clientCredential = new ClientCredential(options.ClientId, options.AppKey);
63-
}
64-
65-
internal virtual async Task<string> AcquireAccessTokenAsync()
66-
{
67-
var result = await _authContext.AcquireTokenAsync(_resourceId, _clientCredential);
68-
return result?.AccessToken;
69-
}
70-
71-
private async Task<string> AcquireTokenWithRetriesAsync(CancellationToken cancellationToken)
72-
{
73-
//
74-
// Get an access token from Azure AD using client credentials.
75-
// If the attempt to get a token fails because the server is unavailable, retry twice after 3 seconds each.
76-
//
77-
string token = null;
78-
int retryCount = 0;
79-
bool retry = false;
80-
81-
do
82-
{
83-
retry = false;
84-
try
85-
{
86-
// ADAL includes an in memory cache, so this call will only send a message to the server if the cached token is expired.
87-
token = await AcquireAccessTokenAsync();
88-
}
89-
catch (AdalException ex)
90-
{
91-
if (ex.ErrorCode == "temporarily_unavailable" && !cancellationToken.IsCancellationRequested)
92-
{
93-
retry = true;
94-
retryCount++;
95-
Thread.Sleep(3000);
96-
}
97-
98-
// Console.WriteLine(
99-
// String.Format("An error occurred while acquiring a token\nTime: {0}\nError: {1}\nRetry: {2}\n",
100-
// DateTime.Now.ToString(),
101-
// ex.ToString(),
102-
// retry.ToString()));
103-
}
104-
105-
} while ((retry == true) && (retryCount < 3) && !cancellationToken.IsCancellationRequested);
106-
107-
return token;
108-
}
109-
110-
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
111-
{
112-
var accessToken = await AcquireTokenWithRetriesAsync(cancellationToken);
113-
if (cancellationToken.IsCancellationRequested)
114-
{
115-
return null;
116-
}
117-
118-
request.Headers.Authorization = new AuthenticationHeaderValue(
119-
"Bearer",
120-
accessToken);
121-
122-
return await base.SendAsync(request, cancellationToken);
123-
}
124-
}
125-
1267
public static class AzureAdAuthenticatedHttpClient
1278
{
1289
public static HttpClient GetClient(AzureAdAuthenticatedHttpClientOptions options, HttpMessageHandler innerHandler = null)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
namespace Patros.AuthenticatedHttpClient
2+
{
3+
// implementation shamelessly ripped off from the Azure sample
4+
// https://github.com/Azure-Samples/active-directory-dotnet-daemon/blob/master/TodoListDaemon/Program.cs
5+
public class AzureAdAuthenticatedHttpClientOptions {
6+
/// <summary>
7+
/// The AAD Instance is the instance of Azure, for example public Azure or Azure China.
8+
/// </summary>
9+
/// <value></value>
10+
public string AadInstance { get; set; } = "https://login.microsoftonline.com/{0}";
11+
12+
/// <summary>
13+
/// The Tenant is the name of the Azure AD tenant in which this application is registered.
14+
/// </summary>
15+
/// <value></value>
16+
public string Tenant { get; set; }
17+
18+
/// <summary>
19+
/// The Client ID is used by the application to uniquely identify itself to Azure AD.
20+
/// </summary>
21+
/// <value></value>
22+
public string ClientId { get; set; }
23+
24+
/// <summary>
25+
/// The App Key is a credential used by the application to authenticate to Azure AD.
26+
/// </summary>
27+
/// <value></value>
28+
public string AppKey { get; set; }
29+
30+
/// <summary>
31+
/// The Resource Id is the id of the service you are contacting/authenticating to.
32+
/// </summary>
33+
/// <value></value>
34+
public string ResourceId { get; set; }
35+
}
36+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System;
2+
using System.Net.Http;
3+
using System.Net.Http.Headers;
4+
using System.Globalization;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Microsoft.IdentityModel.Clients.ActiveDirectory;
8+
9+
namespace Patros.AuthenticatedHttpClient
10+
{
11+
// implementation shamelessly ripped off from the Azure sample
12+
// https://github.com/Azure-Samples/active-directory-dotnet-daemon/blob/master/TodoListDaemon/Program.cs
13+
public class AzureAdAuthenticatedHttpMessageHandler : DelegatingHandler
14+
{
15+
private string _resourceId;
16+
private AuthenticationContext _authContext;
17+
private ClientCredential _clientCredential;
18+
19+
public AzureAdAuthenticatedHttpMessageHandler(AzureAdAuthenticatedHttpClientOptions options, HttpMessageHandler innerHandler = null)
20+
{
21+
InnerHandler = innerHandler ?? new HttpClientHandler();
22+
23+
_resourceId = options.ResourceId;
24+
25+
var authority = String.Format(CultureInfo.InvariantCulture, options.AadInstance, options.Tenant);
26+
_authContext = new AuthenticationContext(authority);
27+
28+
_clientCredential = new ClientCredential(options.ClientId, options.AppKey);
29+
}
30+
31+
internal virtual async Task<string> AcquireAccessTokenAsync()
32+
{
33+
var result = await _authContext.AcquireTokenAsync(_resourceId, _clientCredential);
34+
return result?.AccessToken;
35+
}
36+
37+
private async Task<string> AcquireTokenWithRetriesAsync(CancellationToken cancellationToken)
38+
{
39+
//
40+
// Get an access token from Azure AD using client credentials.
41+
// If the attempt to get a token fails because the server is unavailable, retry twice after 3 seconds each.
42+
//
43+
string token = null;
44+
int retryCount = 0;
45+
bool retry = false;
46+
47+
do
48+
{
49+
retry = false;
50+
try
51+
{
52+
// ADAL includes an in memory cache, so this call will only send a message to the server if the cached token is expired.
53+
token = await AcquireAccessTokenAsync();
54+
}
55+
catch (AdalException ex)
56+
{
57+
if (ex.ErrorCode == "temporarily_unavailable" && !cancellationToken.IsCancellationRequested)
58+
{
59+
retry = true;
60+
retryCount++;
61+
Thread.Sleep(3000);
62+
}
63+
64+
// Console.WriteLine(
65+
// String.Format("An error occurred while acquiring a token\nTime: {0}\nError: {1}\nRetry: {2}\n",
66+
// DateTime.Now.ToString(),
67+
// ex.ToString(),
68+
// retry.ToString()));
69+
}
70+
71+
}
72+
while ((retry == true) && (retryCount < 3) && !cancellationToken.IsCancellationRequested);
73+
74+
return token;
75+
}
76+
77+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
78+
{
79+
var accessToken = await AcquireTokenWithRetriesAsync(cancellationToken);
80+
if (cancellationToken.IsCancellationRequested)
81+
{
82+
return null;
83+
}
84+
85+
request.Headers.Authorization = new AuthenticationHeaderValue(
86+
"Bearer",
87+
accessToken);
88+
89+
return await base.SendAsync(request, cancellationToken);
90+
}
91+
}
92+
}

Patros.AuthenticatedHttpClient.AzureAppServiceManagedIdentity/AzureAppServiceManagedIdentityAuthenticatedHttpClient.cs

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,7 @@
1-
using System;
2-
using System.Net.Http;
3-
using System.Net.Http.Headers;
4-
using System.Threading;
5-
using System.Threading.Tasks;
6-
using Microsoft.Azure.Services.AppAuthentication;
7-
using System.Diagnostics.CodeAnalysis;
1+
using System.Net.Http;
82

93
namespace Patros.AuthenticatedHttpClient
104
{
11-
public class AzureAppServiceManagedIdentityAuthenticatedHttpClientOptions {
12-
/// <summary>
13-
/// The ResourceId is the id of the service you are contacting/authenticating to.
14-
/// </summary>
15-
/// <value></value>
16-
public string ResourceId { get; set; }
17-
}
18-
19-
public class AzureAppServiceManagedIdentityAuthenticatedHttpMessageHandler : DelegatingHandler
20-
{
21-
private string _resourceId;
22-
private AzureServiceTokenProvider _azureServiceTokenProvider = new AzureServiceTokenProvider();
23-
24-
public AzureAppServiceManagedIdentityAuthenticatedHttpMessageHandler(AzureAppServiceManagedIdentityAuthenticatedHttpClientOptions options, HttpMessageHandler innerHandler = null)
25-
{
26-
InnerHandler = innerHandler ?? new HttpClientHandler();
27-
28-
_resourceId = options.ResourceId;
29-
}
30-
31-
[ExcludeFromCodeCoverage]
32-
internal virtual async Task<string> GetAccessTokenAsync()
33-
{
34-
return await _azureServiceTokenProvider.GetAccessTokenAsync(_resourceId);
35-
}
36-
37-
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
38-
{
39-
var accessToken = await GetAccessTokenAsync();
40-
41-
request.Headers.Authorization = new AuthenticationHeaderValue(
42-
"Bearer",
43-
accessToken);
44-
45-
return await base.SendAsync(request, cancellationToken);
46-
}
47-
}
48-
495
public class AzureAppServiceManagedIdentityAuthenticatedHttpClient
506
{
517
public static HttpClient GetClient(AzureAppServiceManagedIdentityAuthenticatedHttpClientOptions options, HttpMessageHandler innerHandler = null)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Patros.AuthenticatedHttpClient
2+
{
3+
public class AzureAppServiceManagedIdentityAuthenticatedHttpClientOptions {
4+
/// <summary>
5+
/// The ResourceId is the id of the service you are contacting/authenticating to.
6+
/// </summary>
7+
/// <value></value>
8+
public string ResourceId { get; set; }
9+
}
10+
}

0 commit comments

Comments
 (0)