Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,23 @@

namespace Azure.Identity
{
internal class IdentityClient
internal class AadClient
{
private static Lazy<IdentityClient> s_sharedClient = new Lazy<IdentityClient>(() => new IdentityClient());
private static Lazy<AadClient> s_sharedClient = new Lazy<AadClient>(() => new AadClient());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any scenarios under which s_sharedClient is rendered unusable? E.g. a fatal error that it is not possible to recover from without recreating the client instance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The client is mostly stateless. The only errors which would render the client useless would be through miss configuration of the process, which would mean the s_sharedClient would never be usable and error on all calls.


private readonly IdentityClientOptions _options;
private readonly HttpPipeline _pipeline;
private readonly Uri ImdsEndptoint = new Uri("http://169.254.169.254/metadata/identity/oauth2/token");
private const string MsiApiVersion = "2018-02-01";

private const string ClientAssertionType = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";

public IdentityClient(IdentityClientOptions options = null)
public AadClient(IdentityClientOptions options = null)
{
_options = options ?? new IdentityClientOptions();

_pipeline = HttpPipelineBuilder.Build(_options, bufferResponse: true);
}

public static IdentityClient SharedClient { get { return s_sharedClient.Value; } }
public static AadClient SharedClient { get { return s_sharedClient.Value; } }


public virtual async Task<AccessToken> AuthenticateAsync(string tenantId, string clientId, string clientSecret, string[] scopes, CancellationToken cancellationToken = default)
Expand Down Expand Up @@ -106,65 +105,6 @@ public virtual AccessToken Authenticate(string tenantId, string clientId, X509Ce
throw response.CreateRequestFailedException();
}
}
public virtual async Task<AccessToken> AuthenticateManagedIdentityAsync(string[] scopes, string clientId = null, CancellationToken cancellationToken = default)
{
using (Request request = CreateManagedIdentityAuthRequest(scopes, clientId))
{
var response = await _pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);

if (response.Status == 200 || response.Status == 201)
{
var result = await DeserializeAsync(response.ContentStream, cancellationToken).ConfigureAwait(false);

return new Response<AccessToken>(response, result);
}

throw response.CreateRequestFailedException();
}
}

public virtual AccessToken AuthenticateManagedIdentity(string[] scopes, string clientId = null, CancellationToken cancellationToken = default)
{
using (Request request = CreateManagedIdentityAuthRequest(scopes, clientId))
{
var response = _pipeline.SendRequest(request, cancellationToken);

if (response.Status == 200 || response.Status == 201)
{
var result = Deserialize(response.ContentStream);

return new Response<AccessToken>(response, result);
}

throw response.CreateRequestFailedException();
}
}

private Request CreateManagedIdentityAuthRequest(string[] scopes, string clientId = null)
{
// covert the scopes to a resource string
string resource = ScopeUtilities.ScopesToResource(scopes);

Request request = _pipeline.CreateRequest();

request.Method = HttpPipelineMethod.Get;

request.Headers.Add("Metadata", "true");

// TODO: support MSI for hosted services
request.UriBuilder.Uri = ImdsEndptoint;

request.UriBuilder.AppendQuery("api-version", MsiApiVersion);

request.UriBuilder.AppendQuery("resource", Uri.EscapeDataString(resource));

if (!string.IsNullOrEmpty(clientId))
{
request.UriBuilder.AppendQuery("client_id", Uri.EscapeDataString(clientId));
}

return request;
}

private Request CreateClientSecretAuthRequest(string tenantId, string clientId, string clientSecret, string[] scopes)
{
Expand Down
3 changes: 1 addition & 2 deletions sdk/identity/Azure.Identity/src/Base64Url.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for
// license information.
// Licensed under the MIT License.

using System;
using System.Text;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for
// license information.
// Licensed under the MIT License.


using Azure.Core;
using System;
Expand All @@ -15,7 +15,7 @@ public class ClientCertificateCredential : TokenCredential
private string _tenantId;
private string _clientId;
private X509Certificate2 _clientCertificate;
private IdentityClient _client;
private AadClient _client;

public ClientCertificateCredential(string tenantId, string clientId, X509Certificate2 clientCertificate)
: this(tenantId, clientId, clientCertificate, null)
Expand All @@ -30,7 +30,7 @@ public ClientCertificateCredential(string tenantId, string clientId, X509Certifi

_clientCertificate = clientCertificate ?? throw new ArgumentNullException(nameof(clientCertificate));

_client = (options != null) ? new IdentityClient(options) : IdentityClient.SharedClient;
_client = (options != null) ? new AadClient(options) : AadClient.SharedClient;
}

public override AccessToken GetToken(string[] scopes, CancellationToken cancellationToken = default)
Expand Down
4 changes: 2 additions & 2 deletions sdk/identity/Azure.Identity/src/ClientSecretCredential.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ClientSecretCredential : TokenCredential
private string _tenantId;
private string _clientId;
private string _clientSecret;
private IdentityClient _client;
private AadClient _client;


public ClientSecretCredential(string tenantId, string clientId, string clientSecret)
Expand All @@ -27,7 +27,7 @@ public ClientSecretCredential(string tenantId, string clientId, string clientSec
_clientId = clientId;
_clientSecret = clientSecret;

_client = (options != null) ? new IdentityClient(options) : IdentityClient.SharedClient;
_client = (options != null) ? new AadClient(options) : AadClient.SharedClient;
}

public override async Task<AccessToken> GetTokenAsync(string[] scopes, CancellationToken cancellationToken = default)
Expand Down
Loading