Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Identity] Adding regional STS support #21590

Merged
merged 10 commits into from
Jun 28, 2021
5 changes: 5 additions & 0 deletions sdk/identity/Azure.Identity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## 1.5.0-beta.1 (Unreleased)

### New Features
- Added regional STS support to client credential types
- Added `RegionalAuthority` extensible enum
- Added `RegionalAuthority` property to `ClientSecretCredentialOptions` and `ClientCertificateCredentialOptions`

### Fixes and improvements

- Added `LoginHint` property to `InteractiveBrowserCredentialOptions` which allows a user name to be pre-selected for interactive logins. Setting this option skips the account selection prompt and immediately attempts to login with the specified account.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public ClientCertificateCredential(string tenantId, string clientId, string clie
public partial class ClientCertificateCredentialOptions : Azure.Identity.TokenCredentialOptions
{
public ClientCertificateCredentialOptions() { }
public Azure.Identity.RegionalAuthority? RegionalAuthority { get { throw null; } set { } }
public bool SendCertificateChain { get { throw null; } set { } }
public Azure.Identity.TokenCachePersistenceOptions TokenCachePersistenceOptions { get { throw null; } set { } }
}
Expand All @@ -94,6 +95,7 @@ public ClientSecretCredential(string tenantId, string clientId, string clientSec
public partial class ClientSecretCredentialOptions : Azure.Identity.TokenCredentialOptions
{
public ClientSecretCredentialOptions() { }
public Azure.Identity.RegionalAuthority? RegionalAuthority { get { throw null; } set { } }
public Azure.Identity.TokenCachePersistenceOptions TokenCachePersistenceOptions { get { throw null; } set { } }
}
public partial class CredentialUnavailableException : Azure.Identity.AuthenticationFailedException
Expand Down Expand Up @@ -210,6 +212,75 @@ public ManagedIdentityCredential(string clientId = null, Azure.Identity.TokenCre
public override Azure.Core.AccessToken GetToken(Azure.Core.TokenRequestContext requestContext, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public override System.Threading.Tasks.ValueTask<Azure.Core.AccessToken> GetTokenAsync(Azure.Core.TokenRequestContext requestContext, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct RegionalAuthority : System.IEquatable<Azure.Identity.RegionalAuthority>
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public RegionalAuthority(string value) { throw null; }
public static Azure.Identity.RegionalAuthority AsiaEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority AsiaSouthEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority AustraliaCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority AustraliaCentral2 { get { throw null; } }
public static Azure.Identity.RegionalAuthority AustraliaEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority AustraliaSouthEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority AutoDiscoverRegion { get { throw null; } }
public static Azure.Identity.RegionalAuthority BrazilSouth { get { throw null; } }
public static Azure.Identity.RegionalAuthority CanadaCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority CanadaEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority ChinaEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority ChinaEast2 { get { throw null; } }
public static Azure.Identity.RegionalAuthority ChinaNorth { get { throw null; } }
public static Azure.Identity.RegionalAuthority ChinaNorth2 { get { throw null; } }
public static Azure.Identity.RegionalAuthority EuropeNorth { get { throw null; } }
public static Azure.Identity.RegionalAuthority EuropeWest { get { throw null; } }
public static Azure.Identity.RegionalAuthority FranceCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority FranceSouth { get { throw null; } }
public static Azure.Identity.RegionalAuthority GermanyCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority GermanyNorth { get { throw null; } }
public static Azure.Identity.RegionalAuthority GermanyNorthEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority GermanyWestCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority GovernmentUSArizona { get { throw null; } }
public static Azure.Identity.RegionalAuthority GovernmentUSDodCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority GovernmentUSDodEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority GovernmentUSIowa { get { throw null; } }
public static Azure.Identity.RegionalAuthority GovernmentUSTexas { get { throw null; } }
public static Azure.Identity.RegionalAuthority GovernmentUSVirginia { get { throw null; } }
public static Azure.Identity.RegionalAuthority IndiaCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority IndiaSouth { get { throw null; } }
public static Azure.Identity.RegionalAuthority IndiaWest { get { throw null; } }
public static Azure.Identity.RegionalAuthority JapanEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority JapanWest { get { throw null; } }
public static Azure.Identity.RegionalAuthority KoreaCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority KoreaSouth { get { throw null; } }
public static Azure.Identity.RegionalAuthority NorwayEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority NorwayWest { get { throw null; } }
public static Azure.Identity.RegionalAuthority SouthAfricaNorth { get { throw null; } }
public static Azure.Identity.RegionalAuthority SouthAfricaWest { get { throw null; } }
public static Azure.Identity.RegionalAuthority SwitzerlandNorth { get { throw null; } }
public static Azure.Identity.RegionalAuthority SwitzerlandWest { get { throw null; } }
public static Azure.Identity.RegionalAuthority UAECentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority UAENorth { get { throw null; } }
public static Azure.Identity.RegionalAuthority UKSouth { get { throw null; } }
public static Azure.Identity.RegionalAuthority UKWest { get { throw null; } }
public static Azure.Identity.RegionalAuthority USCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority USEast { get { throw null; } }
public static Azure.Identity.RegionalAuthority USEast2 { get { throw null; } }
public static Azure.Identity.RegionalAuthority USNorthCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority USSouthCentral { get { throw null; } }
public static Azure.Identity.RegionalAuthority USWest { get { throw null; } }
public static Azure.Identity.RegionalAuthority USWest2 { get { throw null; } }
public static Azure.Identity.RegionalAuthority USWestCentral { get { throw null; } }
public bool Equals(Azure.Identity.RegionalAuthority other) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public override bool Equals(object obj) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public override int GetHashCode() { throw null; }
public static bool operator ==(Azure.Identity.RegionalAuthority left, Azure.Identity.RegionalAuthority right) { throw null; }
public static implicit operator Azure.Identity.RegionalAuthority (string value) { throw null; }
public static bool operator !=(Azure.Identity.RegionalAuthority left, Azure.Identity.RegionalAuthority right) { throw null; }
public override string ToString() { throw null; }
}
public partial class SharedTokenCacheCredential : Azure.Core.TokenCredential
{
public SharedTokenCacheCredential() { }
Expand Down
11 changes: 7 additions & 4 deletions sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public class ClientCertificateCredential : TokenCredential

internal IX509Certificate2Provider ClientCertificateProvider { get; }

private readonly MsalConfidentialClient _client;
internal MsalConfidentialClient Client { get; }

private readonly CredentialPipeline _pipeline;

/// <summary>
Expand Down Expand Up @@ -129,7 +130,9 @@ internal ClientCertificateCredential(string tenantId, string clientId, IX509Cert

_pipeline = pipeline ?? CredentialPipeline.GetInstance(options);

_client = client ?? new MsalConfidentialClient(_pipeline, tenantId, clientId, certificateProvider, (options as ClientCertificateCredentialOptions)?.SendCertificateChain ?? false, options as ITokenCacheOptions);
ClientCertificateCredentialOptions certCredOptions = (options as ClientCertificateCredentialOptions);

Client = client ?? new MsalConfidentialClient(_pipeline, tenantId, clientId, certificateProvider, certCredOptions?.SendCertificateChain ?? false, options as ITokenCacheOptions, certCredOptions?.RegionalAuthority);
}

/// <summary>
Expand All @@ -144,7 +147,7 @@ public override AccessToken GetToken(TokenRequestContext requestContext, Cancell

try
{
AuthenticationResult result = _client.AcquireTokenForClientAsync(requestContext.Scopes, false, cancellationToken).EnsureCompleted();
AuthenticationResult result = Client.AcquireTokenForClientAsync(requestContext.Scopes, false, cancellationToken).EnsureCompleted();

return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn));
}
Expand All @@ -166,7 +169,7 @@ public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext r

try
{
AuthenticationResult result = await _client.AcquireTokenForClientAsync(requestContext.Scopes, true, cancellationToken).ConfigureAwait(false);
AuthenticationResult result = await Client.AcquireTokenForClientAsync(requestContext.Scopes, true, cancellationToken).ConfigureAwait(false);

return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,11 @@ public class ClientCertificateCredentialOptions : TokenCredentialOptions, IToken
/// Will include x5c header in client claims when acquiring a token to enable subject name / issuer based authentication for the <see cref="ClientCertificateCredential"/>.
/// </summary>
public bool SendCertificateChain { get; set; }

/// <summary>
/// Specifies either the specific <see cref="RegionalAuthority"/> (preferred), or use <see cref="RegionalAuthority.AutoDiscoverRegion"/> to attempt to auto-detect the region.
/// If not specified or auto-detection fails the non-regional endpoint will be used.
/// </summary>
public RegionalAuthority? RegionalAuthority { get; set; }
}
}
9 changes: 5 additions & 4 deletions sdk/identity/Azure.Identity/src/ClientSecretCredential.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ namespace Azure.Identity
/// </summary>
public class ClientSecretCredential : TokenCredential
{
private readonly MsalConfidentialClient _client;
private readonly CredentialPipeline _pipeline;

internal MsalConfidentialClient Client { get; }

/// <summary>
/// Gets the Azure Active Directory tenant (directory) Id of the service principal
/// </summary>
Expand Down Expand Up @@ -87,7 +88,7 @@ internal ClientSecretCredential(string tenantId, string clientId, string clientS

_pipeline = pipeline ?? CredentialPipeline.GetInstance(options);

_client = client ?? new MsalConfidentialClient(_pipeline, tenantId, clientId, clientSecret, options as ITokenCacheOptions);
Client = client ?? new MsalConfidentialClient(_pipeline, tenantId, clientId, clientSecret, options as ITokenCacheOptions, (options as ClientSecretCredentialOptions)?.RegionalAuthority);
}

/// <summary>
Expand All @@ -102,7 +103,7 @@ public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext r

try
{
AuthenticationResult result = await _client.AcquireTokenForClientAsync(requestContext.Scopes, true, cancellationToken).ConfigureAwait(false);
AuthenticationResult result = await Client.AcquireTokenForClientAsync(requestContext.Scopes, true, cancellationToken).ConfigureAwait(false);

return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn));
}
Expand All @@ -124,7 +125,7 @@ public override AccessToken GetToken(TokenRequestContext requestContext, Cancell

try
{
AuthenticationResult result = _client.AcquireTokenForClientAsync(requestContext.Scopes, false, cancellationToken).EnsureCompleted();
AuthenticationResult result = Client.AcquireTokenForClientAsync(requestContext.Scopes, false, cancellationToken).EnsureCompleted();

return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,11 @@ public class ClientSecretCredentialOptions : TokenCredentialOptions, ITokenCache
/// Specifies the <see cref="TokenCachePersistenceOptions"/> to be used by the credential. If not options are specified, the token cache will not be persisted.
/// </summary>
public TokenCachePersistenceOptions TokenCachePersistenceOptions { get; set; }

/// <summary>
/// Specifies either the specific <see cref="RegionalAuthority"/> (preferred), or use <see cref="RegionalAuthority.AutoDiscoverRegion"/> to attempt to auto-detect the region.
/// If not specified or auto-detection fails the non-regional endpoint will be used.
/// </summary>
public RegionalAuthority? RegionalAuthority { get; set; }
}
}
13 changes: 11 additions & 2 deletions sdk/identity/Azure.Identity/src/MsalConfidentialClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,23 @@ protected MsalConfidentialClient()
{
}

public MsalConfidentialClient(CredentialPipeline pipeline, string tenantId, string clientId, string clientSecret, ITokenCacheOptions cacheOptions)
public MsalConfidentialClient(CredentialPipeline pipeline, string tenantId, string clientId, string clientSecret, ITokenCacheOptions cacheOptions, RegionalAuthority? regionalAuthority)
: base(pipeline, tenantId, clientId, cacheOptions)
{
_clientSecret = clientSecret;
RegionalAuthority = regionalAuthority;
}

public MsalConfidentialClient(CredentialPipeline pipeline, string tenantId, string clientId, ClientCertificateCredential.IX509Certificate2Provider certificateProvider, bool includeX5CClaimHeader, ITokenCacheOptions cacheOptions)
public MsalConfidentialClient(CredentialPipeline pipeline, string tenantId, string clientId, ClientCertificateCredential.IX509Certificate2Provider certificateProvider, bool includeX5CClaimHeader, ITokenCacheOptions cacheOptions, RegionalAuthority? regionalAuthority)
: base(pipeline, tenantId, clientId, cacheOptions)
{
_includeX5CClaimHeader = includeX5CClaimHeader;
_certificateProvider = certificateProvider;
RegionalAuthority = regionalAuthority;
}

internal RegionalAuthority? RegionalAuthority { get; }

protected override async ValueTask<IConfidentialClientApplication> CreateClientAsync(bool async, CancellationToken cancellationToken)
{
ConfidentialClientApplicationBuilder confClientBuilder = ConfidentialClientApplicationBuilder.Create(ClientId).WithAuthority(Pipeline.AuthorityHost.AbsoluteUri, TenantId).WithHttpClientFactory(new HttpPipelineClientFactory(Pipeline.HttpPipeline));
Expand All @@ -52,6 +56,11 @@ protected override async ValueTask<IConfidentialClientApplication> CreateClientA
confClientBuilder.WithCertificate(clientCertificate);
}

if (RegionalAuthority.HasValue)
{
confClientBuilder.WithAzureRegion(RegionalAuthority.Value.ToString());
}

return confClientBuilder.Build();
}

Expand Down
Loading