diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.IntegrationTests/Helpers/GraphHelper.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.IntegrationTests/Helpers/GraphHelper.cs index 4242d7a7cdb8..739d6d61331d 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.IntegrationTests/Helpers/GraphHelper.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.IntegrationTests/Helpers/GraphHelper.cs @@ -41,7 +41,7 @@ public async Task CreateApplicationAsync(string secret) Application newApp = new Application { DisplayName = $"Microsoft.Azure.Services.AppAuthentication.Test{guid}", - IdentifierUris = new List { $"https://Microsoft.Azure.Services.AppAuthentication/{guid}"}, + IdentifierUris = new List { $"https://Microsoft.Azure.Services.AppAuthentication/{guid}" }, ReplyUrls = new List { "https://Microsoft.Azure.Services.AppAuthentication/" }, OdataType = "Microsoft.DirectoryServices.Application", AppRolesODataType = "Collection(Microsoft.DirectoryServices.AppRole)", @@ -57,7 +57,7 @@ public async Task CreateApplicationAsync(string secret) EndDate = DateTime.Now.AddDays(2) }; - newApp.PasswordCredentials = new List {keyCredential}; + newApp.PasswordCredentials = new List { keyCredential }; return await CreateApplication(newApp).ConfigureAwait(false); @@ -75,7 +75,7 @@ public async Task CreateApplicationAsync(X509Certificate2 cert) Application newApp = new Application { DisplayName = $"Microsoft.Azure.Services.AppAuthentication.Test{guid}", - IdentifierUris = new List { $"https://localhost/demo/{guid}"}, + IdentifierUris = new List { $"https://localhost/demo/{guid}" }, ReplyUrls = new List { "https://localhost/demo" }, OdataType = "Microsoft.DirectoryServices.Application", AppRolesODataType = "Collection(Microsoft.DirectoryServices.AppRole)", @@ -157,7 +157,6 @@ await SendHttpRequest(HttpMethod.Delete, await SendHttpRequest(HttpMethod.Delete, $"{Constants.GraphResourceId}{_directory}/applications/{app.ObjectId}?api-version=1.6").ConfigureAwait(false); - } /// diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.TestCommon/Constants.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.TestCommon/Constants.cs index cd4b6b2ed8fb..933cf214ad96 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.TestCommon/Constants.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.TestCommon/Constants.cs @@ -88,8 +88,8 @@ public class Constants public static readonly string AppType = "App"; // MSI related constants - public static readonly string MsiAppServiceEndpointEnv = "MSI_ENDPOINT"; - public static readonly string MsiAppServiceSecretEnv = "MSI_SECRET"; + public static readonly string MsiAppServiceEndpointEnv = "IDENTITY_ENDPOINT"; + public static readonly string MsiAppServiceHeaderEnv = "IDENTITY_HEADER"; public static readonly string MsiEndpoint = "http://localhost:3748/oauth2/token"; // Unit test certificate diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.TestCommon/Validator.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.TestCommon/Validator.cs index 4876ffbb7cf8..096f404a8aaa 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.TestCommon/Validator.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.TestCommon/Validator.cs @@ -78,9 +78,8 @@ private static DateTimeOffset GetTokenExpiration(string accessTokenString) /// /// /// - public static void ValidateToken(string token, Principal principalUsed, string type, - string tenantId, string appId = default(string), string thumbprint = default(string), - DateTimeOffset expiresOn = default(DateTimeOffset)) + public static void ValidateToken(string token, Principal principalUsed, string type, string tenantId, + string appId = default, string thumbprint = default, DateTimeOffset expiresOn = default) { Assert.Equal("eyJ0eXAiOiJKV1Qi", token.Substring(0, "eyJ0eXAiOiJKV1Qi".Length)); Assert.Contains(".", token); @@ -113,7 +112,7 @@ public static void ValidateToken(string token, Principal principalUsed, string t upnPart = $" UserPrincipalName:{principalUsed.UserPrincipalName}"; } - if (expiresOn != default(DateTimeOffset)) + if (expiresOn != default) { DateTimeOffset tokenExpiration = GetTokenExpiration(token); diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/AzureServiceTokenProviderTests.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/AzureServiceTokenProviderTests.cs index b97cf571d947..136f7cf14288 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/AzureServiceTokenProviderTests.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/AzureServiceTokenProviderTests.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net.Http; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Services.AppAuthentication.TestCommon; @@ -25,7 +27,7 @@ public void Dispose() // Delete environment variables Environment.SetEnvironmentVariable(Constants.TestCertUrlEnv, null); Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, null); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, null); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, null); } /// @@ -45,7 +47,7 @@ public async Task GetAppAuthResultCacheTest() // ManualResetEvent will enable testing of SemaphoreSlim used in AzureServiceTokenProvider. ManualResetEvent manualResetEvent = new ManualResetEvent(false); - + // Use AzureServiceTokenProviders to get tokens in parallel. for (int i = 0; i < 5; i++) { @@ -95,9 +97,9 @@ public async Task GetAppAuthResultCacheTest() // AppAuthResultCache should not return this, since it is about to expire. var tokenResponse = TokenResponse.Parse(TokenHelper.GetUserTokenResponse(5 * 60 - 2)); var authResult = AppAuthenticationResult.Create(tokenResponse); - AppAuthResultCache.AddOrUpdate("ConnectionString:;Authority:;Resource:https://vault.azure.net/", + AppAuthResultCache.AddOrUpdate("ConnectionString:;Authority:;Resource:https://vault.azure.net/", new Tuple(authResult, null)); - + // Get the token again. for (int i = 0; i < 5; i++) { @@ -144,8 +146,8 @@ public async Task GetTokenExceptionTest() [Fact] public void InvalidAzureAdInstanceTest() { - var exception = Assert.Throws(() => new AzureServiceTokenProvider(azureAdInstance:"http://aadinstance/")); - + var exception = Assert.Throws(() => new AzureServiceTokenProvider(azureAdInstance: "http://aadinstance/")); + Assert.Contains(Constants.MustUseHttpsError, exception.ToString()); } @@ -194,7 +196,7 @@ public void UnspecifiedConnectionStringTest() { // Set environment variable AzureServicesAuthConnectionString Environment.SetEnvironmentVariable(Constants.ConnectionStringEnvironmentVariableName, Constants.AzureCliConnectionString); - + var provider = new AzureServiceTokenProvider(); Assert.NotNull(provider); @@ -217,7 +219,7 @@ public async Task DiscoveryTestFirstSuccess() // set env vars so MsiAccessTokenProvider assumes App Service environment and not VM environment Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); // AzureServiceTokenProvider is being asked to use two providers, and return token from the first that succeeds. var providers = new List { azureCliAccessTokenProvider, msiAccessTokenProvider }; @@ -248,10 +250,10 @@ public async Task DiscoveryTestFirstFail() // set env vars so MsiAccessTokenProvider assumes App Service environment and not VM environment Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); // AzureServiceTokenProvider is being asked to use two providers, and return token from the first that succeeds. - var providers = new List{azureCliAccessTokenProvider, msiAccessTokenProvider}; + var providers = new List { azureCliAccessTokenProvider, msiAccessTokenProvider }; AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(providers); var token = await azureServiceTokenProvider.GetAccessTokenAsync(Constants.GraphResourceId, Constants.TenantId); @@ -280,10 +282,10 @@ public void DiscoveryTestBothFail() MockMsi mockMsi = new MockMsi(MockMsi.MsiTestType.MsiAppServicesFailure); HttpClient httpClient = new HttpClient(mockMsi); MsiAccessTokenProvider msiAccessTokenProvider = new MsiAccessTokenProvider(httpClient); - + // set env vars so MsiAccessTokenProvider assumes App Service environment and not VM environment Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); // use test hook to expedite test MsiRetryHelper.WaitBeforeRetry = false; @@ -302,8 +304,8 @@ public void DiscoveryTestBothFail() Assert.Equal(5, mockMsi.HitCount); // Clean up environment variables - Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv,null); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, null); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, null); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, null); } /// @@ -351,5 +353,40 @@ public async Task SideLoadHttpFactory() Assert.EndsWith(MockHttpClientFactory.ExceptionMessage, exception.Message); } + + /// + /// Verify backwards compatibility with constructor and method signatures + /// + [Fact] + public void VerifyPublicSignatures() + { + var KnownPublicCtors = new List() + { + "Void .ctor(System.String, System.String)", + "Void .ctor(System.String, System.String, Microsoft.IdentityModel.Clients.ActiveDirectory.IHttpClientFactory)" + }; + + var KnownPublicMethods = new List() + { + "Microsoft.IdentityModel.Clients.ActiveDirectory.IHttpClientFactory get_HttpClientFactory()", + "Void set_HttpClientFactory(Microsoft.IdentityModel.Clients.ActiveDirectory.IHttpClientFactory)", + "TokenCallback get_KeyVaultTokenCallback()", + "Microsoft.Azure.Services.AppAuthentication.Principal get_PrincipalUsed()", + "System.Threading.Tasks.Task`1[System.String] GetAccessTokenAsync(System.String, System.String, System.Threading.CancellationToken)", + "System.Threading.Tasks.Task`1[System.String] GetAccessTokenAsync(System.String, System.String)", + "System.Threading.Tasks.Task`1[Microsoft.Azure.Services.AppAuthentication.AppAuthenticationResult] GetAuthenticationResultAsync(System.String, System.String, System.Threading.CancellationToken)", + "System.Threading.Tasks.Task`1[Microsoft.Azure.Services.AppAuthentication.AppAuthenticationResult] GetAuthenticationResultAsync(System.String, System.String)", + "Boolean Equals(System.Object)", + "Int32 GetHashCode()", + "System.Type GetType()", + "System.String ToString()" + }; + + var publicCtorSignatures = typeof(AzureServiceTokenProvider).GetConstructors().Select(o => o.ToString()).ToList(); + var publicMethodSignatures = typeof(AzureServiceTokenProvider).GetMethods().Select(o => o.ToString()).ToList(); + + Assert.True(Enumerable.SequenceEqual(KnownPublicCtors.OrderBy(i => i), publicCtorSignatures.OrderBy(i => i))); + Assert.True(Enumerable.SequenceEqual(KnownPublicMethods.OrderBy(i => i), publicMethodSignatures.OrderBy(i => i))); + } } } diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/KeyVaultClientTests.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/KeyVaultClientTests.cs index 83ab7b5f5478..1375ed65ed72 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/KeyVaultClientTests.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/KeyVaultClientTests.cs @@ -43,17 +43,6 @@ public async Task SecretIdentifierInvalidSchemeTest() Assert.Contains(KeyVaultClient.SecretIdentifierInvalidSchemeError, exception.Message); } - [Fact] - public async Task SecretIdentifierInvalidHostTest() - { - KeyVaultClient keyVaultClient = new KeyVaultClient(); - - string secretIdentifier = Constants.TestKeyVaultCertificateSecretIdentifier.Replace("vault.azure.net", "vault.baddudes.net"); - - var exception = await Assert.ThrowsAnyAsync(() => Task.Run(() => keyVaultClient.GetCertificateAsync(secretIdentifier))); - Assert.Contains(KeyVaultClient.SecretIdentifierInvalidHostError, exception.Message); - } - [Fact] public async Task SecretIdentifierInvalidTypeTest() { diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/MsiAccessTokenProviderTests.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/MsiAccessTokenProviderTests.cs index cd3a8944c8a5..060e2bc243d1 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/MsiAccessTokenProviderTests.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/MsiAccessTokenProviderTests.cs @@ -22,7 +22,7 @@ public void Dispose() { // Delete the environment variables Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, null); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, null); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, null); } [Theory] @@ -105,7 +105,7 @@ public async Task GetTokenUsingManagedIdentityAppServices(bool specifyUserAssign { // Setup the environment variables that App Service MSI would setup. Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); string expectedAppId; string managedIdentityArgument; @@ -137,7 +137,7 @@ public async Task GetTokenUsingManagedIdentityAppServices(bool specifyUserAssign } /// - /// Test response when MSI_SECRET in AppServices MSI is invalid. + /// Test response when IDENTITY_HEADER in AppServices MSI is invalid. /// /// [Fact] @@ -145,7 +145,7 @@ public async Task UnauthorizedTest() { // Setup the environment variables Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); // MockMsi is being asked to act like response from App Service MSI failed (unauthorized). MockMsi mockMsi = new MockMsi(MockMsi.MsiTestType.MsiAppServicesUnauthorized); @@ -167,7 +167,7 @@ public async Task IncorrectFormatTest() { // Setup the environment variables Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); MockMsi mockMsi = new MockMsi(MockMsi.MsiTestType.MsiAppServicesIncorrectRequest); HttpClient httpClient = new HttpClient(mockMsi); @@ -188,7 +188,7 @@ public async Task HttpResponseExceptionTest() { // Setup the environment variables Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); MockMsi mockMsi = new MockMsi(MockMsi.MsiTestType.MsiAppServicesFailure); HttpClient httpClient = new HttpClient(mockMsi); @@ -206,7 +206,7 @@ public async Task HttpResponseExceptionTest() public async Task AzureVmImdsTimeoutTest() { Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, null); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, null); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, null); MockMsi mockMsi = new MockMsi(MockMsi.MsiTestType.MsiAzureVmTimeout); HttpClient httpClient = new HttpClient(mockMsi); @@ -226,7 +226,7 @@ internal async Task TransientErrorRetryTest(MockMsi.MsiTestType testType) { // To simplify tests, mock as MSI App Services to skip Azure VM IDMS probe request by Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); MockMsi mockMsi = new MockMsi(testType); HttpClient httpClient = new HttpClient(mockMsi); @@ -259,9 +259,9 @@ private async Task MsiRetryTimeoutTest() { // To simplify tests, mock as MSI App Services to skip Azure VM IDMS probe request Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); - int timeoutInSeconds = (new Random()).Next(1,4); + int timeoutInSeconds = (new Random()).Next(1, 4); MockMsi mockMsi = new MockMsi(MockMsi.MsiTestType.MsiUnresponsive); HttpClient httpClient = new HttpClient(mockMsi); @@ -293,7 +293,7 @@ private async Task AppServicesDifferentCultureTest() // Setup the environment variables that App Service MSI would setup. Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, Constants.MsiEndpoint); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, Constants.ClientSecret); + Environment.SetEnvironmentVariable(Constants.MsiAppServiceHeaderEnv, Constants.ClientSecret); // MockMsi is being asked to act like response from App Service MSI suceeded. MockMsi mockMsi = new MockMsi(MockMsi.MsiTestType.MsiAppServicesSuccess); diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/SqlAppAuthenticationProviderTests.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/SqlAppAuthenticationProviderTests.cs index bb7a192bcd4a..ff90a5f8617c 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/SqlAppAuthenticationProviderTests.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/SqlAppAuthenticationProviderTests.cs @@ -14,7 +14,7 @@ public class SqlAppAuthenticationProviderTests public async void InvalidAuthority() { // Provide authority parameter value that will not parse properly - var parameters = new SqlAppAuthenticationParameters("http://badauthority", Constants.KeyVaultResourceId, default(string)); + var parameters = new SqlAppAuthenticationParameters("http://badauthority", Constants.KeyVaultResourceId, default); // Ensure exception is thrown when getting the token var exception = await Assert.ThrowsAsync(() => (new SqlAppAuthenticationProvider()).AcquireTokenAsync(parameters)); @@ -26,7 +26,7 @@ public async void InvalidAuthority() public async void MissingResource() { // Do not provide any resource parameter value - var parameters = new SqlAppAuthenticationParameters($"{Constants.AzureAdInstance}{Constants.TenantId}", string.Empty, default(string)); + var parameters = new SqlAppAuthenticationParameters($"{Constants.AzureAdInstance}{Constants.TenantId}", string.Empty, default); // Ensure exception is thrown when getting the token var exception = await Assert.ThrowsAsync(() => (new SqlAppAuthenticationProvider()).AcquireTokenAsync(parameters)); @@ -39,7 +39,7 @@ public void InvalidUserId() { string returnValue = SqlAppAuthenticationProvider.GetConnectionStringByUserId("NotAGuid"); - Assert.Equal(default(string), returnValue); + Assert.Equal(default, returnValue); } [Fact] diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/TokenHelper.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/TokenHelper.cs index 7b315654661f..7e3f5ec2b708 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/TokenHelper.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication.Unit.Tests/TokenHelper.cs @@ -70,7 +70,7 @@ internal static string GetUserTokenResponse(long secondsFromCurrent, bool format internal static string GetMsiAppServicesTokenResponse() { return - "{\"access_token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzUU4wQlpTN3M0bk4tQmRyamJGMFlfTGRNTSIsImtpZCI6ImEzUU4wQlpTN3M0bk4tQmRyamJGMFlfTGRNTSJ9.eyJhdWQiOiJodHRwczovL3ZhdWx0LmF6dXJlLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE0OTIyNjYwNjEsIm5iZiI6MTQ5MjI2NjA2MSwiZXhwIjoxNDkyMjY5OTYxLCJhaW8iOiJZMlpnWUNoTk91Yy9ZKzJMOVM3Ty8yWTBDL2lhQUFBPSIsImFwcGlkIjoiZjBiMWY4NGEtZWM3NC00Y2VmLTgwMzQtYWRiYWQxNjhjZTMzIiwiYXBwaWRhY3IiOiIyIiwiZV9leHAiOjI2MjgwMCwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6ImY4NDYwMGM1LWE5ZDgtNDEyOS1hMTk5LWNjNDE4MDYwNzQxMSIsInN1YiI6ImY4NDYwMGM1LWE5ZDgtNDEyOS1hMTk5LWNjNDE4MDYwNzQxMSIsInRpZCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsInZlciI6IjEuMCJ9.TjnKtpTJ_dvQc3GQO9QSA0Sm9MISNakF8IT9-abzkaWqmwruhB2Tls9QTHe-P_xp09Jrt6JPhC8Z5mTTWgKqV_LV-KbJe_NmlYMTU_X5AcaPIQoi2ctSv62-wnnl-2IQjEEkyX7Vc0ixnPdWOG5LCO4ctTmURRO-tWN_jIK5up-wb0-ks1STFSBGJZtJ0xNTdTb9SSG4HpHzbLdkEmg-oAvOBX2OmwaNbBsU3chi4G5MoLtm5oXvL36z9vsf2bN_H7Sg-mss1Ua7OOwFVPMrx0rrIqXzKYQUSvNFAHLebKcp2SccpYWrgp7lKQGrbQhJsYYkzl-R-NTB5fUPUB7B3Q\",\"expires_on\":\"04/15/2017 3:26:01 PM +00:00\",\"resource\":\"https://vault.azure.net\",\"token_type\":\"Bearer\"}"; + "{\"access_token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzUU4wQlpTN3M0bk4tQmRyamJGMFlfTGRNTSIsImtpZCI6ImEzUU4wQlpTN3M0bk4tQmRyamJGMFlfTGRNTSJ9.eyJhdWQiOiJodHRwczovL3ZhdWx0LmF6dXJlLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE0OTIyNjYwNjEsIm5iZiI6MTQ5MjI2NjA2MSwiZXhwIjoxNDkyMjY5OTYxLCJhaW8iOiJZMlpnWUNoTk91Yy9ZKzJMOVM3Ty8yWTBDL2lhQUFBPSIsImFwcGlkIjoiZjBiMWY4NGEtZWM3NC00Y2VmLTgwMzQtYWRiYWQxNjhjZTMzIiwiYXBwaWRhY3IiOiIyIiwiZV9leHAiOjI2MjgwMCwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6ImY4NDYwMGM1LWE5ZDgtNDEyOS1hMTk5LWNjNDE4MDYwNzQxMSIsInN1YiI6ImY4NDYwMGM1LWE5ZDgtNDEyOS1hMTk5LWNjNDE4MDYwNzQxMSIsInRpZCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsInZlciI6IjEuMCJ9.TjnKtpTJ_dvQc3GQO9QSA0Sm9MISNakF8IT9-abzkaWqmwruhB2Tls9QTHe-P_xp09Jrt6JPhC8Z5mTTWgKqV_LV-KbJe_NmlYMTU_X5AcaPIQoi2ctSv62-wnnl-2IQjEEkyX7Vc0ixnPdWOG5LCO4ctTmURRO-tWN_jIK5up-wb0-ks1STFSBGJZtJ0xNTdTb9SSG4HpHzbLdkEmg-oAvOBX2OmwaNbBsU3chi4G5MoLtm5oXvL36z9vsf2bN_H7Sg-mss1Ua7OOwFVPMrx0rrIqXzKYQUSvNFAHLebKcp2SccpYWrgp7lKQGrbQhJsYYkzl-R-NTB5fUPUB7B3Q\",\"expires_on\":\"1589671972\",\"resource\":\"https://vault.azure.net\",\"token_type\":\"Bearer\",\"client_id\":\"F0B1F84A-EC74-4CEF-8034-ADBAD168CE33\"}"; } /// @@ -90,6 +90,7 @@ internal static string GetMsiAzureVmTokenResponse() internal static string GetManagedIdentityAppServicesTokenResponse() { return + //[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Secret is used for tests only")] "{\"access_token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ii1zeE1KTUxDSURXTVRQdlp5SjZ0eC1DRHh3MCIsImtpZCI6Ii1zeE1KTUxDSURXTVRQdlp5SjZ0eC1DRHh3MCJ9.eyJhdWQiOiJodHRwczovL3ZhdWx0LmF6dXJlLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaWF0IjoxNTUwMjc3NjYwLCJuYmYiOjE1NTAyNzc2NjAsImV4cCI6MTU1MDMwNjc2MCwiYWlvIjoiNDJKZ1lPaWZHRnlZUFgrSnRsbXQvdTFucjdjMkFBQT0iLCJhcHBpZCI6Ijk0MjM0M2IxLTRhZjItNDkwYy1iNmQ5LTkyNTBiOGYyODA4YyIsImFwcGlkYWNyIjoiMiIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJvaWQiOiJiMzllNTZiZS1jZThiLTQyYjAtYjY3ZS0xYWI5YmU4ODUxZmQiLCJzdWIiOiJiMzllNTZiZS1jZThiLTQyYjAtYjY3ZS0xYWI5YmU4ODUxZmQiLCJ0aWQiOiI3MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDciLCJ1dGkiOiJUVW9za19PbGkwNlMzZGh6TXVsOEFBIiwidmVyIjoiMS4wIiwieG1zX21pcmlkIjoiL3N1YnNjcmlwdGlvbnMvYmRkNzg5ZjMtZDlkMS00YmVhLWFjMTQtMzBhMzllZDY2ZDMzL3Jlc291cmNlZ3JvdXBzL3Rlc3RiZWQvcHJvdmlkZXJzL01pY3Jvc29mdC5NYW5hZ2VkSWRlbnRpdHkvdXNlckFzc2lnbmVkSWRlbnRpdGllcy9UZXN0QmVkTWFuYWdlZElkZW50aXR5In0.l1E07vTtwSCFasXuFMw1QQXzZutZxFYRjtJhO0L5jyni6L9FO8B2azuIb6ot2KoS5TY-jcvJiLuX-e1Nxu4GlrVAMBukRKjxsyHhYQJ9vppVu7vPFG9EY-GCcamsgkoh6ItbYhDD6sRBqUjTGG2I7lvKNhLg2g92KZiwDhXVtfDPwWLMrnZKmuwOOBwU5UZ61poAmZvw5NO5a8pvXqJ1s5koKo8aPjnCdkJ5WA2SvLbGM_VMo5O6WgLgB4UTC_LnNvsp5nzie2W6Z-VnM_Ar3w1KMeP6_xJZAyEVsxQIgIF3hy12iekpvViwXXUzvthjpeoFobvn65l6NX7fIrNZNQ\",\"expires_on\":\"2/16/2019 8:46:00 AM +00:00\",\"resource\":\"https://vault.azure.net/\",\"token_type\":\"Bearer\"}"; } @@ -100,6 +101,7 @@ internal static string GetManagedIdentityAppServicesTokenResponse() internal static string GetManagedIdentityAzureVmTokenResponse() { return + //[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Secret is used for tests only")] "{\"access_token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ii1zeE1KTUxDSURXTVRQdlp5SjZ0eC1DRHh3MCIsImtpZCI6Ii1zeE1KTUxDSURXTVRQdlp5SjZ0eC1DRHh3MCJ9.eyJhdWQiOiJodHRwczovL3ZhdWx0LmF6dXJlLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaWF0IjoxNTUwMjc4NDkwLCJuYmYiOjE1NTAyNzg0OTAsImV4cCI6MTU1MDMwNzU5MCwiYWlvIjoiNDJKZ1lBaU9YWmxSWXBlZitYcWZaZEFpTnMyN0FBPT0iLCJhcHBpZCI6Ijk0MjM0M2IxLTRhZjItNDkwYy1iNmQ5LTkyNTBiOGYyODA4YyIsImFwcGlkYWNyIjoiMiIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJvaWQiOiJiMzllNTZiZS1jZThiLTQyYjAtYjY3ZS0xYWI5YmU4ODUxZmQiLCJzdWIiOiJiMzllNTZiZS1jZThiLTQyYjAtYjY3ZS0xYWI5YmU4ODUxZmQiLCJ0aWQiOiI3MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDciLCJ1dGkiOiJaUHZPY0tPUE4wYVZicm9lZmhNQUFBIiwidmVyIjoiMS4wIiwieG1zX21pcmlkIjoiL3N1YnNjcmlwdGlvbnMvYmRkNzg5ZjMtZDlkMS00YmVhLWFjMTQtMzBhMzllZDY2ZDMzL3Jlc291cmNlZ3JvdXBzL3Rlc3RiZWQvcHJvdmlkZXJzL01pY3Jvc29mdC5NYW5hZ2VkSWRlbnRpdHkvdXNlckFzc2lnbmVkSWRlbnRpdGllcy9UZXN0QmVkTWFuYWdlZElkZW50aXR5In0.TxlAPmz2_xAgIQUtrz0zP7Y2iid7tiQg3SEMOAMW6P69NngKBR8JZWMZ20K01rHarrxsb_7IaKwFpK4MHadv-ZNcjXeGgA_FdnxKkluNArjCAj-2n3wLeZVE3o8kbmrBCuosEwUCyH69wHINABmz3xLnO5c9OUQXjK7-Z73DfV1ZYWXXBE2HzQlNAyKbTcd4GQng22REahKFj4snuDTt_dvXg1s8pkrnqsz-fCHf1QHK6mk_ds-Y4uz40SyLlVJ_i4PxZtLZYcl-kS-ol0qEKdxYE6ghAVzuwF6DbX-2LAw2QY2mcMIOttyCw4r1V-lTVuTenrG2uOM7syBTJ-4y4A\",\"client_id\":\"942343b1-4af2-490c-b6d9-9250b8f2808c\",\"expires_in\":\"28800\",\"expires_on\":\"1550307590\",\"ext_expires_in\":\"28800\",\"not_before\":\"1550278490\",\"resource\":\"https://vault.azure.net/\",\"token_type\":\"Bearer\"}"; } @@ -121,6 +123,7 @@ internal static string GetMsiMissingTokenResponse() internal static string GetInvalidMsiTokenResponse() { return + //[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Secret is used for tests only")] "{\"access_token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzUU4wQlpTN3M0bk4tQmRyamJGMFlfTGRNTSIsImtpZCI6ImEzUU4wQlpTN3M0bk4tQmRyamJGMFlfTGRNTSJ9.eyJhdWQiOiJodHRwczovL3ZhdWx0LmF6dXJlLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE0OTIyNjYwNjEsIm5iZiI6MTQ5MjI2NjA2MSwiZXhwIjoxNDkyMjY5OTYxLCJhaW8iOiJZMlpnWUNoTk91Yy9ZKzJMOVM3Ty8yWTBDL2lhQUFBPSIsImFwcGlkIjoiZjBiMWY4NGEtZWM3NC00Y2VmLTgwMzQtYWRiYWQxNjhjZTMzIiwiYXBwaWRhY3IiOiIyIiwiZV9leHAiOjI2MjgwMCwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6ImY4NDYwMGM1LWE5ZDgtNDEyOS1hMTk5LWNjNDE4MDYwNzQxMSIsInN1YiI6ImY4NDYwMGM1LWE5ZDgtNDEyOS1hMTk5LWNjNDE4MDYwNzQxMSIsInRpZCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsInZlciI6IjEuMCJ9.TjnKtpTJ_dvQc3GQO9QSA0Sm9MISNakF8IT9-abzkaWqmwruhB2Tls9QTHe-P_xp09Jrt6JPhC8Z5mTTWgKqV_LV-KbJe_NmlYMTU_X5AcaPIQoi2ctSv62-wnnl-2IQjEEkyX7Vc0ixnPdWOG5LCO4ctTmURRO-tWN_jIK5up-wb0-ks1STFSBGJZtJ0xNTdTb9SSG4HpHzbLdkEmg-oAvOBX2OmwaNbBsU3chi4G5MoLtm5oXvL36z9vsf2bN_H7Sg-mss1Ua7OOwFVPMrx0rrIqXzKYQUSvNFAHLebKcp2SccpYWrgp7lKQGrbQhJsYYkzl-R-NTB5fUPUB7B3Q\",\"refresh_token\"\"\",\"expires_in\":\"3600\",\"expires_on\":\"1492269961\",\"not_before\":\"1492266061\",\"resource\":\"https://vault.azure.net\",\"token_type\":\"Bearer\""; } @@ -131,6 +134,7 @@ internal static string GetInvalidMsiTokenResponse() internal static string GetAppToken() { return + //[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Secret is used for tests only")] "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlZXVkljMVdEMVRrc2JiMzAxc2FzTTVrT3E1USIsImtpZCI6IlZXVkljMVdEMVRrc2JiMzAxc2FzTTVrT3E1USJ9.eyJhdWQiOiJodHRwczovL2RhdGFiYXNlLndpbmRvd3MubmV0LyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE1MDMxOTAwNjAsIm5iZiI6MTUwMzE5MDA2MCwiZXhwIjoxNTAzMTkzOTYwLCJfY2xhaW1fbmFtZXMiOnsiZ3JvdXBzIjoic3JjMSJ9LCJfY2xhaW1fc291cmNlcyI6eyJzcmMxIjp7ImVuZHBvaW50IjoiaHR0cHM6Ly9ncmFwaC53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvdXNlcnMvOWNlYjQ0YWYtNDQzNy00Y2NjLWE0OWEtOWE5YmRlMDY3NTJlL2dldE1lbWJlck9iamVjdHMifX0sImFjciI6IjEiLCJhaW8iOiJZMkZnWUxEZVZPZDh6Lzlydy8vM3M4N1plREdYM1NxL21odnBJaDZsdTlqbnlQU0d2bE1BIiwiYW1yIjpbIndpYSIsIm1mYSJdLCJhcHBpZCI6IjA0YjA3Nzk1LThkZGItNDYxYS1iYmVlLTAyZjllMWJmN2I0NiIsImFwcGlkYWNyIjoiMCIsImVfZXhwIjoyNjI4MDAsImZhbWlseV9uYW1lIjoiU2hhcm1hIiwiZ2l2ZW5fbmFtZSI6IlZhcnVuIiwiaW5fY29ycCI6InRydWUiLCJpcGFkZHIiOiIxNjcuMjIwLjAuMjExIiwibmFtZSI6IlZhcnVuIFNoYXJtYSIsIm9pZCI6IjljZWI0NGFmLTQ0MzctNGNjYy1hNDlhLTlhOWJkZTA2NzUyZSIsIm9ucHJlbV9zaWQiOiJTLTEtNS0yMS0yMTI3NTIxMTg0LTE2MDQwMTI5MjAtMTg4NzkyNzUyNy0xODMzNjYyMSIsInB1aWQiOiIxMDAzM0ZGRjgwMUI5MTg4Iiwic2NwIjoidXNlcl9pbXBlcnNvbmF0aW9uIiwic3ViIjoiX1ZCcElTQWVJX0tVQVR2T3Zfd0Vic3ZRNWJWY1BEUi1IbkU1QVJrM29tRSIsInRpZCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsInVuaXF1ZV9uYW1lIjoidmFydW5zaEBtaWNyb3NvZnQuY29tIiwidXBuIjoidmFydW5zaEBtaWNyb3NvZnQuY29tIiwidmVyIjoiMS4wIn0.gGo1wCH2k8kqt6JUdjBMavZX9Sq2L_tKLvVDPUJv3NurZT5JGYyS7gJ11RMrVaxyG48dnlWat1vEBcB-YLOkpL-2gR_sSAoAStPuz8yXAFHxluw-WOqiWxlm2leENqwMmCrMYinm8ohkrScpfRFm6-4fzgczdhNi0vjkTHaycYnrPrH9cZHSL9Qyzt6MH6pEyGct4zmgASI1Vlrga5_x_x8xj-FscIRYorrvx61fThaor8M4FjzglNgum4j5yecn1pIcp75CK43xb7e4jdsfL2nl6wgn5mZj_59b_aKNa3_VA-NmZTlxjvjlL_AHdDkYPlku_B75-0EbfKN2IR5eLw"; } diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AppAuthenticationResult.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AppAuthenticationResult.cs index ef21bfec19c6..9c68f6cd77e8 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AppAuthenticationResult.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AppAuthenticationResult.cs @@ -44,7 +44,7 @@ internal bool IsNearExpiry() return ExpiresOn < DateTimeOffset.UtcNow.AddMinutes(5); } - internal static AppAuthenticationResult Create(TokenResponse response, CultureInfo datetimeCulture = null) + internal static AppAuthenticationResult Create(TokenResponse response) { if (response == null) { @@ -54,12 +54,11 @@ internal static AppAuthenticationResult Create(TokenResponse response, CultureIn string expiresOnString = response.ExpiresOn ?? response.ExpiresOn2; DateTimeOffset expiresOn = DateTimeOffset.MinValue; - double seconds; - if (double.TryParse(expiresOnString, out seconds)) + if (double.TryParse(expiresOnString, out double seconds)) { expiresOn = AppAuthentication.AccessToken.UnixTimeEpoch.AddSeconds(seconds); } - else if (!DateTimeOffset.TryParse(expiresOnString, datetimeCulture, DateTimeStyles.None, out expiresOn)) + else if (!DateTimeOffset.TryParse(expiresOnString, out expiresOn)) { throw new ArgumentException("ExpiresOn in token response could not be parsed"); } diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AzureServiceTokenProvider.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AzureServiceTokenProvider.cs index 6116843fcc11..89e2d5c0096d 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AzureServiceTokenProvider.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AzureServiceTokenProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -70,14 +71,14 @@ public class AzureServiceTokenProvider /// Connection string to specify which option to use to get the token. /// Specify a value for clouds other than the Public Cloud. /// Passed to ADAL to allow proxied connections. Takes precedence over the static property - public AzureServiceTokenProvider(string connectionString = default(string), string azureAdInstance = "https://login.microsoftonline.com/", IHttpClientFactory httpClientFactory = null) + public AzureServiceTokenProvider(string connectionString = default, string azureAdInstance = "https://login.microsoftonline.com/", IHttpClientFactory httpClientFactory = default) { if (string.IsNullOrEmpty(azureAdInstance)) { throw new ArgumentNullException(nameof(azureAdInstance)); } - if (!azureAdInstance.ToLower().StartsWith("https")) + if (!azureAdInstance.ToLowerInvariant().StartsWith("https")) { throw new ArgumentException($"azureAdInstance {azureAdInstance} is not valid. It must use https."); } @@ -85,12 +86,12 @@ public class AzureServiceTokenProvider _azureAdInstance = azureAdInstance; // Check the environment variable to see if a connection string is specified. - if (connectionString == default(string)) + if (connectionString == default) { connectionString = EnvironmentHelper.GetEnvironmentVariable("AzureServicesAuthConnectionString"); } - // injection is nicer than static backdoor. + // prefer parameter over static property var factory = httpClientFactory ?? HttpClientFactory; if (!string.IsNullOrWhiteSpace(connectionString)) @@ -113,6 +114,12 @@ public class AzureServiceTokenProvider } + public AzureServiceTokenProvider(string connectionString, string azureAdInstance) + : this(connectionString, azureAdInstance, default) + { + + } + /// /// This method is for testing only /// @@ -138,7 +145,7 @@ internal AzureServiceTokenProvider(List /// private async Task GetAuthResultAsyncImpl(string resource, string authority, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken = default) { // Check if the auth result is present in cache, for the given connection string, authority, and resource // This is an in-memory global cache, that will be used across instances of this class. @@ -250,8 +257,8 @@ private List GetTokenProviders() /// Access token /// Thrown if resource is null or empty. /// Thrown if access token cannot be acquired. - public virtual async Task GetAccessTokenAsync(string resource, string tenantId = default(string), - CancellationToken cancellationToken = default(CancellationToken)) + public virtual async Task GetAccessTokenAsync(string resource, string tenantId = default, + CancellationToken cancellationToken = default) { var authResult = await GetAuthenticationResultAsync(resource, tenantId, cancellationToken).ConfigureAwait(false); @@ -260,7 +267,7 @@ private List GetTokenProviders() public virtual Task GetAccessTokenAsync(string resource, string tenantId) { - return GetAccessTokenAsync(resource, tenantId, default(CancellationToken)); + return GetAccessTokenAsync(resource, tenantId, default); } /// @@ -277,8 +284,8 @@ public virtual Task GetAccessTokenAsync(string resource, string tenantId /// Access token /// Thrown if resource is null or empty. /// Thrown if access token cannot be acquired. - public virtual Task GetAuthenticationResultAsync(string resource, string tenantId = default(string), - CancellationToken cancellationToken = default(CancellationToken)) + public virtual Task GetAuthenticationResultAsync(string resource, string tenantId = default, + CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(resource)) { @@ -292,7 +299,7 @@ public virtual Task GetAccessTokenAsync(string resource, string tenantId public virtual Task GetAuthenticationResultAsync(string resource, string tenantId) { - return GetAuthenticationResultAsync(resource, tenantId, default(CancellationToken)); + return GetAuthenticationResultAsync(resource, tenantId, default); } } } diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AzureServiceTokenProviderFactory.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AzureServiceTokenProviderFactory.cs index 1927b93c5229..a8934af8740e 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AzureServiceTokenProviderFactory.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/AzureServiceTokenProviderFactory.cs @@ -56,7 +56,7 @@ internal class AzureServiceTokenProviderFactory /// Connection string with authentication option and related parameters. /// /// - internal static NonInteractiveAzureServiceTokenProviderBase Create(string connectionString, string azureAdInstance, IHttpClientFactory httpClientFactory = null) + internal static NonInteractiveAzureServiceTokenProviderBase Create(string connectionString, string azureAdInstance, IHttpClientFactory httpClientFactory = default) { Dictionary connectionSettings = ParseConnectionString(connectionString); @@ -147,7 +147,7 @@ internal static NonInteractiveAzureServiceTokenProviderBase Create(string connec azureAdInstance, connectionSettings.ContainsKey(TenantId) // tenantId can be specified in connection string or retrieved from Key Vault access token later ? connectionSettings[TenantId] - : default(string), + : default, connectionSettings.ContainsKey(MsiRetryTimeout) ? int.Parse(connectionSettings[MsiRetryTimeout]) : 0, diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Clients/KeyVault/KeyVaultClient.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Clients/KeyVault/KeyVaultClient.cs index 78543ad85a91..6757f48dcaf7 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Clients/KeyVault/KeyVaultClient.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Clients/KeyVault/KeyVaultClient.cs @@ -20,19 +20,7 @@ internal class KeyVaultClient private readonly HttpClient _httpClient; private NonInteractiveAzureServiceTokenProviderBase _tokenProvider; - // Key Vault constants and well-known values private const string KeyVaultRestApiVersion = "2016-10-01"; - private const string AzureKeyVaultDnsSuffix = "vault.azure.net"; - private const string ChinaKeyVaultDnsSuffix = "vault.azure.cn"; - private const string USGovernmentKeyVaultDnsSuffix = "vault.usgovcloudapi.net"; - private const string GermanKeyVaultDnsSuffix = "vault.microsoftazure.de"; - private readonly List WellKnownKeyVaultDnsSuffixes = new List() - { - AzureKeyVaultDnsSuffix, - ChinaKeyVaultDnsSuffix, - USGovernmentKeyVaultDnsSuffix, - GermanKeyVaultDnsSuffix - }; // Error messages internal const string BearerChallengeMissingOrInvalidError = "A bearer challenge was not returned or is invalid."; @@ -40,7 +28,6 @@ internal class KeyVaultClient internal const string KeyVaultAccessTokenRetrievalError = "Unable to get a Key Vault access token to acquire certificate."; internal const string KeyVaultResponseError = "Key Vault returned an error."; internal const string SecretBundleInvalidContentTypeError = "Specified secret identifier does not contain private key data. Please check you are providing the secret identifier for the Key Vault client certificate."; - internal const string SecretIdentifierInvalidHostError = "Specified secret identifier has an unrecognized hostname."; internal const string SecretIdentifierInvalidSchemeError = "Specified identifier must use HTTPS."; internal const string SecretIdentifierInvalidTypeError = "Specified identifier is not a secret identifier."; internal const string SecretIdentifierInvalidUriError = "Specified secret identifier is not a valid URI."; @@ -51,7 +38,11 @@ internal class KeyVaultClient internal KeyVaultClient(int msiRetryTimeoutInSeconds = 0, HttpClient httpClient = null, NonInteractiveAzureServiceTokenProviderBase tokenProvider = null) { _msiRetryTimeoutInSeconds = msiRetryTimeoutInSeconds; +#if NETSTANDARD1_4 || net452 || net461 _httpClient = httpClient ?? new HttpClient(); +#else + _httpClient = httpClient ?? new HttpClient(new HttpClientHandler() { CheckCertificateRevocationList = true }); +#endif _tokenProvider = tokenProvider; } @@ -59,7 +50,7 @@ internal KeyVaultClient(HttpClient httpClient, NonInteractiveAzureServiceTokenPr { } - internal async Task GetCertificateAsync(string secretIdentifier, CancellationToken cancellationToken = default(CancellationToken)) + internal async Task GetCertificateAsync(string secretIdentifier, CancellationToken cancellationToken = default) { try { @@ -127,10 +118,6 @@ private void ValidateSecretIdentifier(string secretIdentifier) if (!secretUri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase)) throw new Exception(SecretIdentifierInvalidSchemeError); - // Ensure secret URI host ends in well-known Key Vault DNS suffix - if (!WellKnownKeyVaultDnsSuffixes.Any(dnsSuffix => secretUri.Host.EndsWith(dnsSuffix, StringComparison.OrdinalIgnoreCase))) - throw new Exception(SecretIdentifierInvalidHostError); - // Ensure secret URI is actually a secret identifier (and not key or certificate identifier) if (!secretUri.LocalPath.StartsWith("/secrets/", StringComparison.OrdinalIgnoreCase)) throw new Exception(SecretIdentifierInvalidTypeError); diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Microsoft.Azure.Services.AppAuthentication.csproj b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Microsoft.Azure.Services.AppAuthentication.csproj index 0379dcb3f603..fb66c2061539 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Microsoft.Azure.Services.AppAuthentication.csproj +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Microsoft.Azure.Services.AppAuthentication.csproj @@ -2,15 +2,17 @@ Microsoft.Azure.Services.AppAuthentication Enables a service to authenticate to Azure services using the developer's Azure Active Directory/ Microsoft account during development, and authenticate as itself (using OAuth 2.0 Client Credentials flow) when deployed to Azure. - 1.4.0 + 1.5.0 Microsoft.Azure.Services.AppAuthentication Azure Authentication AppAuthentication diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Properties/AssemblyInfo.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Properties/AssemblyInfo.cs index ebc9ad69cab5..9696e1eec7a3 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Properties/AssemblyInfo.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/Properties/AssemblyInfo.cs @@ -4,8 +4,8 @@ [assembly: AssemblyTitle("Microsoft.Azure.Services.AppAuthentication")] [assembly: AssemblyDescription("Enables a service to authenticate to Azure services using the developer's Azure Active Directory/ Microsoft account during development, and authenticate as itself (using OAuth 2.0 Client Credentials flow) when deployed to Azure.")] -[assembly: AssemblyVersion("1.4.0.0")] -[assembly: AssemblyFileVersion("1.4.0.0")] +[assembly: AssemblyVersion("1.5.0.0")] +[assembly: AssemblyFileVersion("1.5.0.0")] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyProduct("Microsoft Azure")] [assembly: AssemblyCopyright("Copyright (c) Microsoft Corporation. All rights reserved.")] diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/SqlAppAuthenticationProvider.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/SqlAppAuthenticationProvider.cs index f3eb814e91c8..c58c8265e724 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/SqlAppAuthenticationProvider.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/SqlAppAuthenticationProvider.cs @@ -30,7 +30,7 @@ internal static string GetConnectionStringByUserId(string userId) return $"RunAs=App;AppId={userId}"; } - return default(string); + return default; } /// diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/AzureCliAccessTokenProvider.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/AzureCliAccessTokenProvider.cs index 9871276f01fe..dc42931760c7 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/AzureCliAccessTokenProvider.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/AzureCliAccessTokenProvider.cs @@ -94,7 +94,7 @@ private ProcessStartInfo GetProcessStartInfo(string resource) public override async Task GetAuthResultAsync(string resource, string authority, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken = default) { try { diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/ClientCertificateAccessTokenProvider.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/ClientCertificateAccessTokenProvider.cs index d1e4dd19a957..7778b10ae0c4 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/ClientCertificateAccessTokenProvider.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/ClientCertificateAccessTokenProvider.cs @@ -55,7 +55,7 @@ internal enum CertificateIdentifierType /// internal ClientCertificateAzureServiceTokenProvider(string clientId, string certificateIdentifier, CertificateIdentifierType certificateIdentifierType, string storeLocation, - string azureAdInstance, string tenantId = default(string), int msiRetryTimeoutInSeconds = 0, + string azureAdInstance, string tenantId = default, int msiRetryTimeoutInSeconds = 0, IAuthenticationContext authenticationContext = null, KeyVaultClient keyVaultClient = null) { if (string.IsNullOrWhiteSpace(clientId)) @@ -115,7 +115,7 @@ internal ClientCertificateAzureServiceTokenProvider(string clientId, /// Authority where resource is. /// public override async Task GetAuthResultAsync(string resource, string authority, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken = default) { // If authority is not specified and tenantId was present in connection string, create it using azureAdInstance and tenantId. if (string.IsNullOrWhiteSpace(authority) && !string.IsNullOrWhiteSpace(_tenantId)) diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/ClientSecretAccessTokenProvider.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/ClientSecretAccessTokenProvider.cs index 734518afd564..6eaf3302da37 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/ClientSecretAccessTokenProvider.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/ClientSecretAccessTokenProvider.cs @@ -46,7 +46,7 @@ internal ClientSecretAccessTokenProvider(string clientId, string clientSecret, } public override async Task GetAuthResultAsync(string resource, string authority, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken = default) { string errorMessage = string.Empty; diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/MsiAccessTokenProvider.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/MsiAccessTokenProvider.cs index c2b9ae6f3d2c..6a3fd99a1886 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/MsiAccessTokenProvider.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/MsiAccessTokenProvider.cs @@ -22,7 +22,11 @@ internal class MsiAccessTokenProvider : NonInteractiveAzureServiceTokenProviderB private readonly string _managedIdentityClientId; // HttpClient is intended to be instantiated once and re-used throughout the life of an application. +#if NETSTANDARD1_4 || net452 || net461 private static readonly HttpClient DefaultHttpClient = new HttpClient(); +#else + private static readonly HttpClient DefaultHttpClient = new HttpClient(new HttpClientHandler() { CheckCertificateRevocationList = true }); +#endif // Azure Instance Metadata Service (IMDS) endpoint private const string AzureVmImdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token"; @@ -34,7 +38,7 @@ internal class MsiAccessTokenProvider : NonInteractiveAzureServiceTokenProviderB // Configurable timeout for MSI retry logic internal readonly int _retryTimeoutInSeconds = 0; - internal MsiAccessTokenProvider(int retryTimeoutInSeconds = 0, string managedIdentityClientId = default(string)) + internal MsiAccessTokenProvider(int retryTimeoutInSeconds = 0, string managedIdentityClientId = default) { // require storeLocation if using subject name or thumbprint identifier if (retryTimeoutInSeconds < 0) @@ -55,7 +59,7 @@ internal MsiAccessTokenProvider(HttpClient httpClient, int retryTimeoutInSeconds } public override async Task GetAuthResultAsync(string resource, string authority, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken = default) { // Use the httpClient specified in the constructor. If it was not specified in the constructor, use the default httpClient. HttpClient httpClient = _httpClient ?? DefaultHttpClient; @@ -63,9 +67,9 @@ public override async Task GetAuthResultAsync(string re try { // Check if App Services MSI is available. If both these environment variables are set, then it is. - string msiEndpoint = Environment.GetEnvironmentVariable("MSI_ENDPOINT"); - string msiSecret = Environment.GetEnvironmentVariable("MSI_SECRET"); - var isAppServicesMsiAvailable = !string.IsNullOrWhiteSpace(msiEndpoint) && !string.IsNullOrWhiteSpace(msiSecret); + string msiEndpoint = Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT"); + string msiHeader = Environment.GetEnvironmentVariable("IDENTITY_HEADER"); + var isAppServicesMsiAvailable = !string.IsNullOrWhiteSpace(msiEndpoint) && !string.IsNullOrWhiteSpace(msiHeader); // if App Service MSI is not available then Azure VM IMDS may be available, test with a probe request if (!isAppServicesMsiAvailable) @@ -95,14 +99,13 @@ public override async Task GetAuthResultAsync(string re } // If managed identity is specified, include client ID parameter in request - string clientIdParameterName = isAppServicesMsiAvailable ? "clientid" : "client_id"; - string clientIdParameter = _managedIdentityClientId != default(string) - ? $"&{clientIdParameterName}={_managedIdentityClientId}" + string clientIdParameter = _managedIdentityClientId != default + ? $"&client_id={_managedIdentityClientId}" : string.Empty; // Craft request as per the MSI protocol var requestUrl = isAppServicesMsiAvailable - ? $"{msiEndpoint}?resource={resource}{clientIdParameter}&api-version=2017-09-01" + ? $"{msiEndpoint}?resource={resource}{clientIdParameter}&api-version=2019-08-01" : $"{AzureVmImdsEndpoint}?resource={resource}{clientIdParameter}&api-version=2018-02-01"; Func getRequestMessage = () => @@ -111,7 +114,7 @@ public override async Task GetAuthResultAsync(string re if (isAppServicesMsiAvailable) { - request.Headers.Add("Secret", msiSecret); + request.Headers.Add("X-IDENTITY-HEADER", msiHeader); } else { @@ -150,13 +153,8 @@ public override async Task GetAuthResultAsync(string re PrincipalUsed.AppId = token.AppId; PrincipalUsed.TenantId = token.TenantId; } - - // App Services MSI returns en-US format datetime strings - var datetimeCulture = isAppServicesMsiAvailable - ? new CultureInfo("en-US") - : null; - return AppAuthenticationResult.Create(tokenResponse, datetimeCulture); + return AppAuthenticationResult.Create(tokenResponse); } string errorStatusDetail = response.IsRetryableStatusCode() diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/VisualStudioAccessTokenProvider.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/VisualStudioAccessTokenProvider.cs index ee3fa274de84..3b816fcd0a29 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/VisualStudioAccessTokenProvider.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/VisualStudioAccessTokenProvider.cs @@ -65,7 +65,7 @@ private VisualStudioTokenProviderFile GetTokenProviderFile() /// /// private List GetProcessStartInfos(VisualStudioTokenProviderFile visualStudioTokenProviderFile, - string resource, string tenant = default(string)) + string resource, string tenant = default) { List processStartInfos = new List(); @@ -76,7 +76,7 @@ private List GetProcessStartInfos(VisualStudioTokenProviderFil { string arguments = $"{ResourceArgumentName} {resource} "; - if (tenant != default(string)) + if (tenant != default) { arguments += $"{TenantArgumentName} {tenant} "; } @@ -101,7 +101,7 @@ private List GetProcessStartInfos(VisualStudioTokenProviderFil } public override async Task GetAuthResultAsync(string resource, string authority, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken = default) { try { diff --git a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/WindowsAuthenticationAccessTokenProvider.cs b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/WindowsAuthenticationAccessTokenProvider.cs index 4cb81c7113d4..648f6421ad1a 100644 --- a/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/WindowsAuthenticationAccessTokenProvider.cs +++ b/sdk/mgmtcommon/AppAuthentication/Azure.Services.AppAuthentication/TokenProviders/WindowsAuthenticationAccessTokenProvider.cs @@ -36,7 +36,7 @@ internal WindowsAuthenticationAzureServiceTokenProvider(IAuthenticationContext a /// Authority where resource is present. /// public override async Task GetAuthResultAsync(string resource, string authority, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken = default) { // If authority is not specified, start with common. Once known, after the first time token is acquired, use that. if (string.IsNullOrWhiteSpace(authority))