diff --git a/tests/CacheCompat/CommonCache.Test.Unit/CacheExecutionTests.cs b/tests/CacheCompat/CommonCache.Test.Unit/CacheExecutionTests.cs index 5c6ebcd696..f7750a386c 100644 --- a/tests/CacheCompat/CommonCache.Test.Unit/CacheExecutionTests.cs +++ b/tests/CacheCompat/CommonCache.Test.Unit/CacheExecutionTests.cs @@ -19,12 +19,13 @@ public class CacheExecutionTests private static async Task GetPublicAadUserDataAsync() { - var labUser = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); return new LabUserData( - labUser.User.Upn, - labUser.User.GetOrFetchPassword(), - labUser.App.AppId, - labUser.User.TenantId); + user.Upn, + user.GetOrFetchPassword(), + app.AppId, + user.TenantId); } [AssemblyInitialize] diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/CiamIntegrationTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/CiamIntegrationTests.cs index eb1642f7bd..b9ace1d903 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/CiamIntegrationTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/CiamIntegrationTests.cs @@ -32,40 +32,41 @@ public async Task ROPC_Ciam_StandardDomains_CompletesSuccessfully() { string authority; //Get lab details - var labResponse = await LabUserHelper.GetCIAMUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserCiam).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppCiam).ConfigureAwait(false); //https://tenantName.ciamlogin.com/ - authority = string.Format("https://{0}.ciamlogin.com/", labResponse.User.LabName); - await RunCiamRopcTest(authority, labResponse).ConfigureAwait(false); + authority = string.Format("https://{0}.ciamlogin.com/", user.LabName); + await RunCiamRopcTest(authority, user, app).ConfigureAwait(false); //https://tenantName.ciamlogin.com/tenantName.onmicrosoft.com - authority = string.Format("https://{0}.ciamlogin.com/{1}.onmicrosoft.com", labResponse.User.LabName, labResponse.User.LabName); - await RunCiamRopcTest(authority, labResponse).ConfigureAwait(false); + authority = string.Format("https://{0}.ciamlogin.com/{1}.onmicrosoft.com", user.LabName, user.LabName); + await RunCiamRopcTest(authority, user, app).ConfigureAwait(false); //https://tenantName.ciamlogin.com/tenantGuid - authority = string.Format("https://{0}.ciamlogin.com/{1}", labResponse.User.LabName, labResponse.Lab.TenantId); - await RunCiamRopcTest(authority, labResponse).ConfigureAwait(false); + authority = string.Format("https://{0}.ciamlogin.com/{1}", user.LabName, user.TenantId); + await RunCiamRopcTest(authority, user, app).ConfigureAwait(false); } - private async Task RunCiamRopcTest(string authority, LabResponse labResponse) + private async Task RunCiamRopcTest(string authority, UserConfig user, AppConfig app) { //Acquire tokens var msalPublicClient = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority(new Uri(authority), false) .WithRedirectUri(_ciamRedirectUri) .Build(); #pragma warning disable CS0618 // Type or member is obsolete var result = await msalPublicClient - .AcquireTokenByUsernamePassword(_ciamScopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + .AcquireTokenByUsernamePassword(_ciamScopes, user.Upn, user.GetOrFetchPassword()) .ExecuteAsync() .ConfigureAwait(false); #pragma warning restore CS0618 Assert.IsNotNull(result.AccessToken); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); - Assert.AreEqual($"{labResponse.User.LabName}{Constants.CiamAuthorityHostSuffix}".ToLower(), result.Account.Environment); + Assert.AreEqual($"{user.LabName}{Constants.CiamAuthorityHostSuffix}".ToLower(), result.Account.Environment); //Fetch cached tokens var accounts = await msalPublicClient.GetAccountsAsync().ConfigureAwait(false); @@ -77,7 +78,7 @@ private async Task RunCiamRopcTest(string authority, LabResponse labResponse) Assert.IsNotNull(result.AccessToken); Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource); - Assert.AreEqual($"{labResponse.User.LabName}{Constants.CiamAuthorityHostSuffix}".ToLower(), result.Account.Environment); + Assert.AreEqual($"{user.LabName}{Constants.CiamAuthorityHostSuffix}".ToLower(), result.Account.Environment); } [TestMethod] @@ -85,20 +86,20 @@ public async Task ClientCredentialCiam_WithClientCredentials_ReturnsValidTokens( { string authority; //Get lab details - var labResponse = await LabUserHelper.GetCIAMUserAsync().ConfigureAwait(false); - + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserCiam).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppCiam).ConfigureAwait(false); //https://tenantName.ciamlogin.com/ - authority = string.Format("https://{0}.ciamlogin.com/", labResponse.User.LabName); - await RunCiamCCATest(authority, labResponse.App.AppId).ConfigureAwait(false); + authority = string.Format("https://{0}.ciamlogin.com/", user.LabName); + await RunCiamCCATest(authority, app.AppId).ConfigureAwait(false); //https://tenantName.ciamlogin.com/tenantName.onmicrosoft.com - authority = string.Format("https://{0}.ciamlogin.com/{1}.onmicrosoft.com", labResponse.User.LabName, labResponse.User.LabName); - await RunCiamCCATest(authority, labResponse.App.AppId).ConfigureAwait(false); + authority = string.Format("https://{0}.ciamlogin.com/{1}.onmicrosoft.com", user.LabName, user.LabName); + await RunCiamCCATest(authority, app.AppId).ConfigureAwait(false); //https://tenantName.ciamlogin.com/tenantGuid - authority = string.Format("https://{0}.ciamlogin.com/{1}", labResponse.User.LabName, labResponse.Lab.TenantId); - await RunCiamCCATest(authority, labResponse.App.AppId).ConfigureAwait(false); + authority = string.Format("https://{0}.ciamlogin.com/{1}", user.LabName, user.TenantId); + await RunCiamCCATest(authority, app.AppId).ConfigureAwait(false); //Ciam CUD authority = "https://login.msidlabsciam.com/fe362aec-5d43-45d1-b730-9755e60dc3b9/v2.0/"; @@ -150,18 +151,19 @@ public async Task OBOCiam_CustomDomain_ReturnsValidTokens() string ciamWebApi = "634de702-3173-4a71-b336-a4fab786a479"; //Get lab details - LabResponse labResponse = await LabUserHelper.GetCIAMUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserCiam).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppCiam).ConfigureAwait(false); //Acquire tokens var msalPublicClient = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) - .WithAuthority(labResponse.App.Authority, false) - .WithRedirectUri(labResponse.App.RedirectUri) + .Create(app.AppId) + .WithAuthority(app.Authority, false) + .WithRedirectUri(app.RedirectUri) .Build(); #pragma warning disable CS0618 // Type or member is obsolete var result = await msalPublicClient - .AcquireTokenByUsernamePassword(new[] { labResponse.App.DefaultScopes }, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + .AcquireTokenByUsernamePassword(new[] { app.DefaultScopes }, user.Upn, user.GetOrFetchPassword()) .ExecuteAsync() .ConfigureAwait(false); #pragma warning restore CS0618 @@ -208,18 +210,19 @@ public async Task OBOCiam_CustomDomain_ReturnsValidTokens() public async Task WithOidcAuthority_ValidatesIssuerSuccessfully() { //Get lab details - var labResponse = await LabUserHelper.GetCIAMUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserCiam).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppCiam).ConfigureAwait(false); //Test with standard and CUD CIAM authorities string[] authorities = { - string.Format("https://{0}.ciamlogin.com/{1}/v2.0/", labResponse.Lab.TenantId, labResponse.Lab.TenantId), - string.Format("https://login.msidlabsciam.com/{0}/v2.0/", labResponse.Lab.TenantId) + string.Format("https://{0}.ciamlogin.com/{1}/v2.0/", user.TenantId, user.TenantId), + string.Format("https://login.msidlabsciam.com/{0}/v2.0/", user.TenantId) }; foreach (var authority in authorities) { - await RunCiamCCATest(authority, labResponse.App.AppId, true).ConfigureAwait(false); + await RunCiamCCATest(authority, app.AppId, true).ConfigureAwait(false); } } diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ClientCredentialsTests.NetFwk.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ClientCredentialsTests.NetFwk.cs index 91f01831fd..9ef9714065 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ClientCredentialsTests.NetFwk.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ClientCredentialsTests.NetFwk.cs @@ -223,26 +223,27 @@ public async Task WithOnBeforeTokenRequest_TestAsync(Cloud cloud, TargetFramewor public async Task ByRefreshTokenTestAsync() { // Arrange - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); var msalPublicClient = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithTestLogging() - .WithAuthority(labResponse.Lab.Authority, "organizations") + .WithAuthority(app.Authority, "organizations") .BuildConcrete(); #pragma warning disable CS0618 // Type or member is obsolete AuthenticationResult authResult = await msalPublicClient - .AcquireTokenByUsernamePassword(s_scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + .AcquireTokenByUsernamePassword(s_scopes, user.Upn, user.GetOrFetchPassword()) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); #pragma warning restore CS0618 - var confidentialApp = ConfidentialClientApplicationBuilder - .Create(labResponse.App.AppId) - .WithAuthority(labResponse.Lab.Authority, labResponse.User.TenantId) - .WithTestLogging() - .BuildConcrete(); +var confidentialApp = ConfidentialClientApplicationBuilder + .Create(app.AppId) + .WithAuthority(app.Authority, user.TenantId) + .WithTestLogging() + .BuildConcrete(); var rt = msalPublicClient.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().FirstOrDefault(); @@ -262,12 +263,12 @@ public async Task ByRefreshTokenTestAsync() // Assert Assert.IsNotNull(authResult); - Assert.AreEqual(labResponse.User.Upn, authResult.Account.Username); - Assert.AreEqual(labResponse.User.ObjectId.ToString(), authResult.Account.HomeAccountId.ObjectId); - Assert.AreEqual(labResponse.User.TenantId, authResult.Account.HomeAccountId.TenantId); - Assert.AreEqual(labResponse.User.Upn, account2.Username); - Assert.AreEqual(labResponse.User.ObjectId.ToString(), account2.HomeAccountId.ObjectId); - Assert.AreEqual(labResponse.User.TenantId, account2.HomeAccountId.TenantId); + Assert.AreEqual(user.Upn, authResult.Account.Username); + Assert.AreEqual(user.ObjectId.ToString(), authResult.Account.HomeAccountId.ObjectId); + Assert.AreEqual(user.TenantId, authResult.Account.HomeAccountId.TenantId); + Assert.AreEqual(user.Upn, account2.Username); + Assert.AreEqual(user.ObjectId.ToString(), account2.HomeAccountId.ObjectId); + Assert.AreEqual(user.TenantId, account2.HomeAccountId.TenantId); } private static void ModifyRequest(OnBeforeTokenRequestData data, X509Certificate2 certificate) diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/InstanceDiscoveryIntegrationTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/InstanceDiscoveryIntegrationTests.cs index cc050eadbd..e4ff059d30 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/InstanceDiscoveryIntegrationTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/InstanceDiscoveryIntegrationTests.cs @@ -30,12 +30,12 @@ public class InstanceDiscoveryIntegrationTests [TestMethod] public async Task AuthorityMigrationAsync() { - LabResponse labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); - LabUser user = labResponse.User; + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) - .WithAuthority("https://login.windows.net/" + labResponse.Lab.TenantId + "/") + .Create(app.AppId) + .WithAuthority("https://login.windows.net/" + user.TenantId + "/") .WithTestLogging() .Build(); @@ -49,7 +49,7 @@ public async Task AuthorityMigrationAsync() // BugBug https://identitydivision.visualstudio.com/Engineering/_workitems/edit/776308/ // sts.windows.net fails when doing instance discovery, e.g.: // https://sts.windows.net/common/discovery/instance?api-version=1.1&authorization_endpoint=https%3A%2F%2Fsts.windows.net%2Ff645ad92-e38d-4d1a-b510-d1b09a74a8ca%2Foauth2%2Fv2.0%2Fauthorize - .WithTenantId(labResponse.Lab.TenantId) + .WithTenantId(user.TenantId) .ExecuteAsync() .ConfigureAwait(false); #pragma warning restore CS0618 @@ -69,11 +69,11 @@ public async Task AuthorityMigrationAsync() [TestMethod] public async Task FailedAuthorityValidationTestAsync() { - LabResponse labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - LabUser user = labResponse.User; + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority("https://bogus.microsoft.com/common") .WithTestLogging() .Build(); @@ -97,11 +97,11 @@ public async Task FailedAuthorityValidationTestAsync() [TestMethod] public async Task AuthorityValidationTestWithFalseValidateAuthorityAsync() { - LabResponse labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - LabUser user = labResponse.User; + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority("https://bogus.microsoft.com/common", false) .WithTestLogging() .Build(); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/LongRunningOnBehalfOfTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/LongRunningOnBehalfOfTests.cs index 358cef30ca..6ed9b4284d 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/LongRunningOnBehalfOfTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/LongRunningOnBehalfOfTests.cs @@ -51,10 +51,10 @@ public void TestInitialize() [TestMethod] public async Task LongRunningAndNormalObo_WithDifferentKeys_TestAsync() { - var labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - var user1 = labResponse.User; + var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); var pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); @@ -104,10 +104,10 @@ public async Task LongRunningAndNormalObo_WithDifferentKeys_TestAsync() [TestMethod] public async Task LongRunningThenNormalObo_WithTheSameKey_TestAsync() { - var labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - var user1 = labResponse.User; + var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); var pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); @@ -178,10 +178,10 @@ public async Task LongRunningThenNormalObo_WithTheSameKey_TestAsync() public async Task InitiateLRWithCustomKey_ThenAcquireLRWithSameKey_Succeeds_TestAsync() { // Arrange - var labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - LabUser user1 = labResponse.User; + var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); @@ -250,10 +250,10 @@ public async Task InitiateLRWithCustomKey_ThenAcquireLRWithSameKey_Succeeds_Test [TestMethod] public async Task NormalOboThenLongRunningAcquire_WithTheSameKey_TestAsync() { - var labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - LabUser user1 = labResponse.User; + var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); var pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); @@ -322,10 +322,10 @@ public async Task NormalOboThenLongRunningAcquire_WithTheSameKey_TestAsync() [TestMethod] public async Task NormalOboThenLongRunningInitiate_WithTheSameKey_TestAsync() { - var labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - var user1 = labResponse.User; + var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); var pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); @@ -380,10 +380,10 @@ public async Task NormalOboThenLongRunningInitiate_WithTheSameKey_TestAsync() public async Task WithDifferentScopes_TestAsync() { string[] scopes2 = { "api://23c64cd8-21e4-41dd-9756-ab9e2c23f58c/access_as_user" }; - var labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - var user1 = labResponse.User; + var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); var pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") .Build(); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ManagedIdentityTests.NetFwk.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ManagedIdentityTests.NetFwk.cs index 509bd94329..1fb4596e1b 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ManagedIdentityTests.NetFwk.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ManagedIdentityTests.NetFwk.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Linq.Expressions; using System.Net; @@ -69,9 +70,9 @@ public async Task AcquireMSITokenAsync(MsiAzureResource azureResource, string us //Arrange using (new EnvVariableContext()) { - // Fetch the env variables from the resource and set them locally + // Fetch the env variables from Key Vault and set them locally Dictionary envVariables = - await GetEnvironmentVariablesAsync(azureResource).ConfigureAwait(false); + await LabResponseHelper.GetDefaultMSIEnvironmentVariablesAsync().ConfigureAwait(false); //Set the Environment Variables SetEnvironmentVariables(envVariables); @@ -124,9 +125,9 @@ public async Task AcquireMsiToken_ForTokenExchangeResource_Successfully() //Arrange using (new EnvVariableContext()) { - // Fetch the env variables from the resource and set them locally + // Fetch the env variables from Key Vault and set them locally Dictionary envVariables = - await GetEnvironmentVariablesAsync(MsiAzureResource.WebApp).ConfigureAwait(false); + await LabResponseHelper.GetDefaultMSIEnvironmentVariablesAsync().ConfigureAwait(false); //Set the Environment Variables SetEnvironmentVariables(envVariables); @@ -179,9 +180,9 @@ public async Task AcquireMsiToken_ExchangeForEstsToken_Successfully() //Arrange using (new EnvVariableContext()) { - // Fetch the env variables from the resource and set them locally + // Fetch the env variables from Key Vault and set them locally Dictionary envVariables = - await GetEnvironmentVariablesAsync(MsiAzureResource.WebApp).ConfigureAwait(false); + await LabResponseHelper.GetDefaultMSIEnvironmentVariablesAsync().ConfigureAwait(false); //Set the Environment Variables SetEnvironmentVariables(envVariables); @@ -284,9 +285,9 @@ public async Task ManagedIdentityRequestFailureCheckAsync(MsiAzureResource azure //Arrange using (new EnvVariableContext()) { - //Get the Environment Variables + //Get the Environment Variables from Key Vault Dictionary envVariables = - await GetEnvironmentVariablesAsync(azureResource).ConfigureAwait(false); + await LabResponseHelper.GetDefaultMSIEnvironmentVariablesAsync().ConfigureAwait(false); //Set the Environment Variables SetEnvironmentVariables(envVariables); @@ -326,9 +327,9 @@ public async Task MSIWrongScopesAsync(MsiAzureResource azureResource, string use //Arrange using (new EnvVariableContext()) { - //Get the Environment Variables + //Get the Environment Variables from Key Vault Dictionary envVariables = - await GetEnvironmentVariablesAsync(azureResource).ConfigureAwait(false); + await LabResponseHelper.GetDefaultMSIEnvironmentVariablesAsync().ConfigureAwait(false); //Set the Environment Variables SetEnvironmentVariables(envVariables); @@ -367,7 +368,7 @@ public async Task AcquireMSITokenWithClaimsAsync( using (new EnvVariableContext()) { // ---------- Arrange ---------- - var envVariables = await GetEnvironmentVariablesAsync(azureResource).ConfigureAwait(false); + var envVariables = await LabResponseHelper.GetDefaultMSIEnvironmentVariablesAsync().ConfigureAwait(false); SetEnvironmentVariables(envVariables); string uri = s_baseURL + $"MSIToken?azureresource={azureResource}&uri="; @@ -416,38 +417,6 @@ public async Task AcquireMSITokenWithClaimsAsync( } } - /// - /// Gets the environment variable - /// - /// - /// - private async Task> GetEnvironmentVariablesAsync( - MsiAzureResource resource) - { - Dictionary environmentVariables = new Dictionary(); - - //Get the Environment Variables from the MSI Helper Service - string uri = s_baseURL + "EnvironmentVariables?resource=" + resource; - - var environmentVariableResponse = await LabUserHelper - .GetMSIEnvironmentVariablesAsync(uri) - .ConfigureAwait(false); - - //process the response - if (!string.IsNullOrEmpty(environmentVariableResponse)) - { -#if NET8_0_OR_GREATER - environmentVariables = System.Text.Json.JsonSerializer.Deserialize - >(environmentVariableResponse); -#else - environmentVariables = Microsoft.Identity.Json.JsonConvert.DeserializeObject - >(environmentVariableResponse); -#endif - } - - return environmentVariables; - } - /// /// Sets the Environment Variables /// diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/OnBehalfOfTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/OnBehalfOfTests.cs index ffa1e80daf..80e9028fd8 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/OnBehalfOfTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/OnBehalfOfTests.cs @@ -58,15 +58,15 @@ public void TestInitialize() public async Task OboAndSilent_ReturnsCorrectTokens_TestAsync(bool serializeCache, bool usePartitionedSerializationCache) { // Setup: Get lab users, create PCA and get user tokens - var user1 = (await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false)).User; - var user2 = (await LabUserHelper.GetDefaultUser2Async().ConfigureAwait(false)).User; - var labResponse1 = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); + var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var user2 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud2).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); var partitionedInMemoryTokenCache = new InMemoryPartitionedTokenCache(); var nonPartitionedInMemoryTokenCache = new InMemoryTokenCache(); var oboTokens = new HashSet(); var pca = PublicClientApplicationBuilder - .Create(labResponse1.App.AppId) + .Create(app.AppId) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); @@ -178,11 +178,11 @@ IConfidentialClientApplication CreateCCA() public async Task OboAndClientCredentials_WithRegional_ReturnsCorrectTokens_TestAsync() { // Setup: Get lab user, create PCA and get user tokens - var user = (await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false)).User; + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); // Use the correct public client ID from KeyVault for all tests - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); - var publicClientId = labResponse.App.AppId; + var publicClientId = app.AppId; var pca = PublicClientApplicationBuilder .Create(publicClientId) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) @@ -232,9 +232,9 @@ public async Task OboAndClientCredentials_WithRegional_ReturnsCorrectTokens_Test [TestMethod] public async Task WithMultipleUsers_TestAsync() { - var aadUser1 = (await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false)).User; - var aadUser2 = (await LabUserHelper.GetDefaultUser2Async().ConfigureAwait(false)).User; - var aadUser3 = (await LabUserHelper.GetDefaultUser3Async().ConfigureAwait(false)).User; + var aadUser1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var aadUser2 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud2).ConfigureAwait(false); + var aadUser3 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserXcg).ConfigureAwait(false); await RunOnBehalfOfTestAsync(aadUser3, false).ConfigureAwait(false); await RunOnBehalfOfTestAsync(aadUser1, false).ConfigureAwait(false); @@ -249,7 +249,8 @@ public async Task WithMultipleUsers_TestAsync() [TestCategory(TestCategories.Arlington)] public async Task ArlingtonWebAPIAccessingGraphOnBehalfOfUserTestAsync() { - var arligntonUser = (await LabUserHelper.GetArlingtonUserAsync().ConfigureAwait(false)).User; + var arligntonUser = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserArlington).ConfigureAwait(false); + arligntonUser.AzureEnvironment = LabConstants.AzureEnvironmentUsGovernment; var msalPublicClient = PublicClientApplicationBuilder.Create("cb7faed4-b8c0-49ee-b421-f5ed16894c83") .WithAuthority("https://login.microsoftonline.us/organizations") @@ -299,12 +300,12 @@ public async Task ArlingtonWebAPIAccessingGraphOnBehalfOfUserTestAsync() [TestMethod] public async Task WithCache_TestAsync() { - var labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - LabUser user = labResponse.User; + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); var factory = new HttpSnifferClientFactory(); - var msalPublicClient = PublicClientApplicationBuilder.Create(labResponse.App.AppId) + var msalPublicClient = PublicClientApplicationBuilder.Create(app.AppId) .WithAuthority(TestConstants.AuthorityOrganizationsTenant) .WithRedirectUri(TestConstants.RedirectUri) .WithTestLogging() @@ -419,7 +420,7 @@ void AssertLastHttpContent(string content) } private async Task RunOnBehalfOfTestAsync( - LabUser user, + UserConfig user, bool silentCallShouldSucceed, bool forceRefresh = false, string multiTenantAppId = null) @@ -429,8 +430,8 @@ private async Task RunOnBehalfOfTestAsync( // Get multiTenantAppId if not provided if (string.IsNullOrEmpty(multiTenantAppId)) { - var labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - multiTenantAppId = labResponse.App.AppId; + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); + multiTenantAppId = app.AppId; } var pca = PublicClientApplicationBuilder diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/PoPTests.NetFwk.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/PoPTests.NetFwk.cs index c3f6b1b61c..0504725575 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/PoPTests.NetFwk.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/PoPTests.NetFwk.cs @@ -66,7 +66,6 @@ public async Task PoP_MultipleKeys_Async() [RunOn(TargetFrameworks.NetCore)] public async Task PoP_BearerAndPoP_CanCoexist_Async() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); await BearerAndPoP_CanCoexist_Async().ConfigureAwait(false); } @@ -300,12 +299,13 @@ public async Task PopTestWithRSAAsync() public async Task ROPC_PopTestWithRSAAsync() { var settings = ConfidentialAppSettings.GetSettings(Cloud.Public); - var labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); // Use the lab response app and tenant for consistency instead of mixing configurations var confidentialApp = ConfidentialClientApplicationBuilder - .Create(labResponse.App.AppId) - .WithAuthority($"https://login.microsoftonline.com/{labResponse.User.TenantId}") + .Create(app.AppId) + .WithAuthority($"https://login.microsoftonline.com/{user.TenantId}") .WithClientSecret(settings.Secret) // Still use the certificate/secret from settings .WithExperimentalFeatures(true) .Build(); @@ -315,14 +315,14 @@ public async Task ROPC_PopTestWithRSAAsync() popConfig.PopCryptoProvider = new RSACertificatePopCryptoProvider(GetCertificate()); popConfig.HttpMethod = HttpMethod.Get; - var result = await (confidentialApp as IByUsernameAndPassword).AcquireTokenByUsernamePassword(s_ropcScope, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + var result = await (confidentialApp as IByUsernameAndPassword).AcquireTokenByUsernamePassword(s_ropcScope, user.Upn, user.GetOrFetchPassword()) .WithSignedHttpRequestProofOfPossession(popConfig) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual("pop", result.TokenType); PoPValidator.VerifyPoPToken( - labResponse.App.AppId, // Use consistent app ID from lab response + app.AppId, // Use consistent app ID from lab response ProtectedUrl, HttpMethod.Get, result); @@ -715,14 +715,15 @@ public async Task PoPToken_ShouldHaveCorrectAlgorithm_PS256_Async() [IgnoreOnOneBranch] public async Task WamUsernamePasswordRequestWithPOPAsync() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string[] scopes = { "User.Read" }; WamLoggerValidator wastestLogger = new WamLoggerValidator(); IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .Create(app.AppId) + .WithAuthority(app.Authority, "organizations") .WithLogging(wastestLogger) .WithBroker(new BrokerOptions(BrokerOptions.OperatingSystems.Windows)) .Build(); @@ -733,18 +734,18 @@ public async Task WamUsernamePasswordRequestWithPOPAsync() var result = await pca .AcquireTokenByUsernamePassword( scopes, - labResponse.User.Upn, - labResponse.User.GetOrFetchPassword()) + user.Upn, + user.GetOrFetchPassword()) .WithProofOfPossession("nonce", HttpMethod.Get, new Uri(ProtectedUrl)) .ExecuteAsync().ConfigureAwait(false); #pragma warning restore CS0618 - MsalAssert.AssertAuthResult(result, TokenSource.Broker, labResponse.Lab.TenantId, scopes, true); + MsalAssert.AssertAuthResult(result, TokenSource.Broker, user.TenantId, scopes, true); Assert.IsTrue(wastestLogger.HasLogged); PoPValidator.VerifyPoPToken( - labResponse.App.AppId, + app.AppId, ProtectedUrl, HttpMethod.Get, result); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/RuntimeBrokerTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/RuntimeBrokerTests.cs index 52896c6ce1..448c4fe388 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/RuntimeBrokerTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/RuntimeBrokerTests.cs @@ -97,7 +97,8 @@ public async Task WamSilentAuthUserInteractionRequiredAsync() [TestMethod] public async Task ExtractNonceWithAuthParserAndValidateShrAsync() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string[] scopes = { "User.Read" }; //Arrange & Act @@ -105,8 +106,8 @@ public async Task ExtractNonceWithAuthParserAndValidateShrAsync() var parsedHeaders = await AuthenticationHeaderParser.ParseAuthenticationHeadersAsync("https://testingsts.azurewebsites.net/servernonce/invalidsignature").ConfigureAwait(false); IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .Create(app.AppId) + .WithAuthority(app.Authority, "organizations") .WithBroker(_brokerOptions) .Build(); @@ -118,8 +119,8 @@ public async Task ExtractNonceWithAuthParserAndValidateShrAsync() var result = await pca .AcquireTokenByUsernamePassword( scopes, - labResponse.User.Upn, - labResponse.User.GetOrFetchPassword()) + user.Upn, + user.GetOrFetchPassword()) .WithProofOfPossession( parsedHeaders.PopNonce, HttpMethod.Get, @@ -130,11 +131,11 @@ public async Task ExtractNonceWithAuthParserAndValidateShrAsync() MsalAssert.AssertAuthResult( result, TokenSource.Broker, - labResponse.Lab.TenantId, + user.TenantId, scopes, true); PoPValidator.VerifyPoPToken( - labResponse.App.AppId, + app.AppId, requestUri.AbsoluteUri, HttpMethod.Get, result); @@ -145,13 +146,14 @@ public async Task ExtractNonceWithAuthParserAndValidateShrAsync() [TestMethod] public async Task WamInvalidROPC_ThrowsException_TestAsync() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string[] scopes = { "User.Read" }; WamLoggerValidator wastestLogger = new WamLoggerValidator(); IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .Create(app.AppId) + .WithAuthority(app.Authority, "organizations") .WithLogging(wastestLogger, enablePiiLogging: true) // it's important that the PII is turned on, otherwise context is 'pii' .WithBroker(_brokerOptions) .Build(); @@ -208,7 +210,8 @@ public async Task WamSilentAuthLoginHintNoAccontInCacheAsync() [TestMethod] public async Task WamUsernamePasswordRequestAsync() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string[] scopes = { "User.Read" }; IntPtr intPtr = TestUtils.GetWindowHandle(); @@ -216,9 +219,9 @@ public async Task WamUsernamePasswordRequestAsync() Func windowHandleProvider = () => intPtr; IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithParentActivityOrWindow(windowHandleProvider) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .WithAuthority(app.Authority, "organizations") .WithLogging((x, y, z) => Debug.WriteLine($"{x} {y}"), LogLevel.Verbose, true) .WithBroker(_brokerOptions) .Build(); @@ -228,9 +231,9 @@ public async Task WamUsernamePasswordRequestAsync() // Acquire token using username password #pragma warning disable CS0618 // Type or member is obsolete - var result = await pca.AcquireTokenByUsernamePassword(scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()).ExecuteAsync().ConfigureAwait(false); + var result = await pca.AcquireTokenByUsernamePassword(scopes, user.Upn, user.GetOrFetchPassword()).ExecuteAsync().ConfigureAwait(false); #pragma warning restore CS0618 - MsalAssert.AssertAuthResult(result, TokenSource.Broker, labResponse.Lab.TenantId, scopes); + MsalAssert.AssertAuthResult(result, TokenSource.Broker, user.TenantId, scopes); Assert.IsNotNull(result.AuthenticationResultMetadata.Telemetry); // Get Accounts @@ -243,7 +246,7 @@ public async Task WamUsernamePasswordRequestAsync() // Acquire token silently result = await pca.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false); - MsalAssert.AssertAuthResult(result, TokenSource.Broker, labResponse.Lab.TenantId, scopes); + MsalAssert.AssertAuthResult(result, TokenSource.Broker, user.TenantId, scopes); Assert.IsNotNull(result.AuthenticationResultMetadata.Telemetry); // Remove Account @@ -266,12 +269,13 @@ public async Task WamWithSSHCertificateAuthenticationSchemeAsync() { IntPtr intPtr = TestUtils.GetWindowHandle(); Func windowHandleProvider = () => intPtr; - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); IPublicClientApplication pca = PublicClientApplicationBuilder .Create(_SSH_ClientId) .WithTestLogging() - .WithAuthority(labResponse.Lab.Authority, "organizations") + .WithAuthority(app.Authority, "organizations") .WithParentActivityOrWindow(windowHandleProvider) .WithBroker(_brokerOptions) .Build(); @@ -280,7 +284,7 @@ public async Task WamWithSSHCertificateAuthenticationSchemeAsync() //Do a login with username password #pragma warning disable CS0618 // Type or member is obsolete AuthenticationResult result = await pca - .AcquireTokenByUsernamePassword(_SSH_scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + .AcquireTokenByUsernamePassword(_SSH_scopes, user.Upn, user.GetOrFetchPassword()) .ExecuteAsync() .ConfigureAwait(false); #pragma warning restore CS0618 @@ -305,16 +309,17 @@ public async Task WamWithSSHCertificateAuthenticationSchemeAsync() [TestMethod] public async Task WamUsernamePasswordWithForceRefreshAsync() { - var labResponse = await LabUserHelper.MergeKVLabDataAsync("MSAL-User-Default-JSON", "ID4SLAB1", "MSAL-APP-AzureADMultipleOrgsPC-JSON").ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgsPublicClient).ConfigureAwait(false); string[] scopes = { "User.Read" }; IntPtr intPtr = TestUtils.GetWindowHandle(); Func windowHandleProvider = () => intPtr; IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithParentActivityOrWindow(windowHandleProvider) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .WithAuthority(app.Authority, "organizations") .WithLogging((x, y, z) => Debug.WriteLine($"{x} {y}"), LogLevel.Verbose, true) .WithBroker(_brokerOptions) .Build(); @@ -323,15 +328,15 @@ public async Task WamUsernamePasswordWithForceRefreshAsync() #pragma warning disable CS0618 // Type or member is obsolete var result = await pca.AcquireTokenByUsernamePassword( scopes, - labResponse.User.Upn, - labResponse.User.GetOrFetchPassword()) + user.Upn, + user.GetOrFetchPassword()) .ExecuteAsync() .ConfigureAwait(false); #pragma warning restore CS0618 string ropcToken = result.AccessToken; - MsalAssert.AssertAuthResult(result, TokenSource.Broker, labResponse.Lab.TenantId, scopes); + MsalAssert.AssertAuthResult(result, TokenSource.Broker, user.TenantId, scopes); Assert.IsNotNull(result.AuthenticationResultMetadata.Telemetry); // Get Accounts @@ -358,7 +363,8 @@ public async Task WamUsernamePasswordWithForceRefreshAsync() [ExpectedException(typeof(MsalUiRequiredException))] public async Task WamUsernamePasswordRequestAsync_WithPiiAsync() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string[] scopes = { "User.Read" }; IntPtr intPtr = TestUtils.GetWindowHandle(); @@ -368,19 +374,19 @@ public async Task WamUsernamePasswordRequestAsync_WithPiiAsync() WamLoggerValidator testLogger = new WamLoggerValidator(); IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithParentActivityOrWindow(windowHandleProvider) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .WithAuthority(app.Authority, "organizations") .WithLogging(testLogger, enablePiiLogging: true) .WithBroker(_brokerOptions) .Build(); // Acquire token using username password #pragma warning disable CS0618 // Type or member is obsolete - var result = await pca.AcquireTokenByUsernamePassword(scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()).ExecuteAsync().ConfigureAwait(false); + var result = await pca.AcquireTokenByUsernamePassword(scopes, user.Upn, user.GetOrFetchPassword()).ExecuteAsync().ConfigureAwait(false); #pragma warning restore CS0618 - MsalAssert.AssertAuthResult(result, TokenSource.Broker, labResponse.Lab.TenantId, scopes); + MsalAssert.AssertAuthResult(result, TokenSource.Broker, user.TenantId, scopes); Assert.IsNotNull(result.AuthenticationResultMetadata.Telemetry); // Get Accounts @@ -396,7 +402,7 @@ public async Task WamUsernamePasswordRequestAsync_WithPiiAsync() // Acquire token silently result = await pca.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false); - MsalAssert.AssertAuthResult(result, TokenSource.Broker, labResponse.Lab.TenantId, scopes); + MsalAssert.AssertAuthResult(result, TokenSource.Broker, user.TenantId, scopes); Assert.IsNotNull(result.AuthenticationResultMetadata.Telemetry); await pca.RemoveAsync(account).ConfigureAwait(false); @@ -413,7 +419,8 @@ public async Task WamUsernamePasswordRequestAsync_WithPiiAsync() [TestMethod] public async Task WamListWindowsWorkAndSchoolAccountsAsync() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string[] scopes = { "User.Read" }; IntPtr intPtr = TestUtils.GetWindowHandle(); @@ -421,9 +428,9 @@ public async Task WamListWindowsWorkAndSchoolAccountsAsync() Func windowHandleProvider = () => intPtr; IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithParentActivityOrWindow(windowHandleProvider) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .WithAuthority(app.Authority, "organizations") .WithBroker(new BrokerOptions(BrokerOptions.OperatingSystems.Windows) { ListOperatingSystemAccounts = true, @@ -432,10 +439,10 @@ public async Task WamListWindowsWorkAndSchoolAccountsAsync() // Acquire token using username password #pragma warning disable CS0618 // Type or member is obsolete - var result = await pca.AcquireTokenByUsernamePassword(scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()).ExecuteAsync().ConfigureAwait(false); + var result = await pca.AcquireTokenByUsernamePassword(scopes, user.Upn, user.GetOrFetchPassword()).ExecuteAsync().ConfigureAwait(false); #pragma warning restore CS0618 - MsalAssert.AssertAuthResult(result, TokenSource.Broker, labResponse.Lab.TenantId, scopes); + MsalAssert.AssertAuthResult(result, TokenSource.Broker, user.TenantId, scopes); Assert.IsNotNull(result.AuthenticationResultMetadata.Telemetry); // Get Accounts @@ -445,7 +452,7 @@ public async Task WamListWindowsWorkAndSchoolAccountsAsync() //This test does not actually get a work or school account //it simply validates that the GetAccounts merging works and accounts are returned var account = accounts.FirstOrDefault(); - Assert.AreEqual(labResponse.User.Upn, account.Username); + Assert.AreEqual(user.Upn, account.Username); } [IgnoreOnOneBranch] @@ -486,7 +493,8 @@ public async Task WamAddDefaultScopesWhenNoScopesArePassedAsync(string scopes) public async Task WamUsernamePasswordPopTokenEnforcedWithCaOnValidResourceAsync() { //Arrange - var labResponse = await LabUserHelper.MergeKVLabDataAsync("MSAL-User-POP-JSON", "ID4SLAB1", "MSAL-APP-AzureADMultipleOrgsPC-JSON").ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPop).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string[] scopes = { "https://id4slab1.sharepoint.com/user.read" }; @@ -495,9 +503,9 @@ public async Task WamUsernamePasswordPopTokenEnforcedWithCaOnValidResourceAsync( Func windowHandleProvider = () => intPtr; IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithParentActivityOrWindow(windowHandleProvider) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .WithAuthority(app.Authority, "organizations") .WithBroker(_brokerOptions) .Build(); @@ -505,14 +513,14 @@ public async Task WamUsernamePasswordPopTokenEnforcedWithCaOnValidResourceAsync( // CA policy enforces token issuance to popUser only for SPO // https://learn.microsoft.com/azure/active-directory/conditional-access/concept-token-protection #pragma warning disable CS0618 // Type or member is obsolete - var result = await pca.AcquireTokenByUsernamePassword(scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + var result = await pca.AcquireTokenByUsernamePassword(scopes, user.Upn, user.GetOrFetchPassword()) .WithProofOfPossession("some_nonce", System.Net.Http.HttpMethod.Get, new Uri(pca.Authority)) .ExecuteAsync() .ConfigureAwait(false); #pragma warning restore CS0618 //Act - Assert.AreEqual(labResponse.User.Upn, result.Account.Username); + Assert.AreEqual(user.Upn, result.Account.Username); } [DoNotRunOnLinux] // POP are not supported on Linux @@ -522,7 +530,8 @@ public async Task WamUsernamePasswordPopTokenEnforcedWithCaOnValidResourceAsync( public async Task WamUsernamePasswordPopTokenEnforcedWithCaOnInValidResourceAsync() { //Arrange - var labResponse = await LabUserHelper.MergeKVLabDataAsync("MSAL-User-POP-JSON", "ID4SLAB1", "MSAL-APP-AzureADMultipleOrgsPC-JSON").ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPop).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string[] scopes = { "https://outlook.office365.com/Mail.Read" }; @@ -531,9 +540,9 @@ public async Task WamUsernamePasswordPopTokenEnforcedWithCaOnInValidResourceAsyn Func windowHandleProvider = () => intPtr; IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithParentActivityOrWindow(windowHandleProvider) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .WithAuthority(app.Authority, "organizations") .WithBroker(_brokerOptions) .Build(); @@ -541,7 +550,7 @@ public async Task WamUsernamePasswordPopTokenEnforcedWithCaOnInValidResourceAsyn // CA policy enforces token issuance to popUser only for Exchange Online this call will fail with UI Required Exception // https://learn.microsoft.com/azure/active-directory/conditional-access/concept-token-protection #pragma warning disable CS0618 // Type or member is obsolete - var result = await pca.AcquireTokenByUsernamePassword(scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + var result = await pca.AcquireTokenByUsernamePassword(scopes, user.Upn, user.GetOrFetchPassword()) .WithProofOfPossession("some_nonce", System.Net.Http.HttpMethod.Get, new Uri(pca.Authority)) .ExecuteAsync() .ConfigureAwait(false); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/SilentAuthTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/SilentAuthTests.cs index 09e777ce9c..0acea2b534 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/SilentAuthTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/SilentAuthTests.cs @@ -30,10 +30,11 @@ public class SilentAuthTests [TestMethod] public async Task SilentAuth_ForceRefresh_Async() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority("https://login.microsoftonline.com/organizations") .WithTestLogging() .Build(); @@ -41,19 +42,19 @@ public async Task SilentAuth_ForceRefresh_Async() Trace.WriteLine("Part 1 - Acquire a token with U/P"); #pragma warning disable CS0618 // Type or member is obsolete AuthenticationResult authResult = await pca - .AcquireTokenByUsernamePassword(s_scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + .AcquireTokenByUsernamePassword(s_scopes, user.Upn, user.GetOrFetchPassword()) .ExecuteAsync(new CancellationTokenSource().Token) .ConfigureAwait(false); #pragma warning restore CS0618 - await ValidateAuthResultAsync(authResult, labResponse).ConfigureAwait(false); + await ValidateAuthResultAsync(authResult, user).ConfigureAwait(false); } [TestMethod] public async Task SilentAuth_TokenCacheRemainsPersistent_Async() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); - var user = labResponse.User; + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string cacheFilePath = null; try @@ -61,7 +62,7 @@ public async Task SilentAuth_TokenCacheRemainsPersistent_Async() cacheFilePath = Path.GetTempFileName(); var pca1 = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithTestLogging() .WithAuthority("https://login.microsoftonline.com/organizations") .Build(); @@ -82,7 +83,7 @@ public async Task SilentAuth_TokenCacheRemainsPersistent_Async() // simulate a restart by creating a new client var pca2 = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithTestLogging() .Build(); @@ -106,41 +107,41 @@ public async Task SilentAuth_TokenCacheRemainsPersistent_Async() private async Task ValidateAuthResultAsync( AuthenticationResult authResult, - LabResponse labResponse) + UserConfig user) { - MsalAssert.AssertAuthResult(authResult, labResponse.User); + MsalAssert.AssertAuthResult(authResult, user); var at1 = authResult.AccessToken; // If test fails with "user needs to consent to the application, do an interactive request" error - see UsernamePassword tests Trace.WriteLine("Part 2 - Acquire a token silently, with forceRefresh = true"); - IAccount account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, authResult).ConfigureAwait(false); + IAccount account = await MsalAssert.AssertSingleAccountAsync(user, pca, authResult).ConfigureAwait(false); authResult = await pca.AcquireTokenSilent(s_scopes, account) .WithForceRefresh(true) .ExecuteAsync() .ConfigureAwait(false); - MsalAssert.AssertAuthResult(authResult, labResponse.User); + MsalAssert.AssertAuthResult(authResult, user); var at2 = authResult.AccessToken; - string tenantId = labResponse.User.UserType == UserType.MSA ? + string tenantId = user.UserType == LabConstants.UserTypeMSA ? Constants.MsaTenantId : - labResponse.User.TenantId; + user.TenantId; Assert.AreEqual( $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token", authResult.AuthenticationResultMetadata.TokenEndpoint); Trace.WriteLine("Part 3 - Acquire a token silently with a login hint, with forceRefresh = true"); - authResult = await pca.AcquireTokenSilent(s_scopes, labResponse.User.Upn) + authResult = await pca.AcquireTokenSilent(s_scopes, user.Upn) .WithForceRefresh(true) .ExecuteAsync() .ConfigureAwait(false); - MsalAssert.AssertAuthResult(authResult, labResponse.User); + MsalAssert.AssertAuthResult(authResult, user); var at3 = authResult.AccessToken; - tenantId = labResponse.User.UserType == UserType.MSA ? + tenantId = user.UserType == LabConstants.UserTypeMSA ? Constants.MsaTenantId : - labResponse.User.TenantId; + user.TenantId; Assert.IsFalse(at1.Equals(at2, System.StringComparison.InvariantCultureIgnoreCase)); Assert.IsFalse(at1.Equals(at3, System.StringComparison.InvariantCultureIgnoreCase)); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/UsernamePasswordIntegrationTests.NetFwk.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/UsernamePasswordIntegrationTests.NetFwk.cs index 3dfdba5f5c..810453d511 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/UsernamePasswordIntegrationTests.NetFwk.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/UsernamePasswordIntegrationTests.NetFwk.cs @@ -44,23 +44,27 @@ public void TestInitialize() [TestMethod] public async Task ROPC_AAD_Async() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); - await RunHappyPathTestAsync(labResponse).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); + await RunHappyPathTestAsync(user, app).ConfigureAwait(false); } [TestMethod] public async Task ROPC_AAD_CCA_Async() { - var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); - await RunHappyPathTestAsync(labResponse: labResponse, isPublicClient: false).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); + await RunHappyPathTestAsync(user, app, isPublicClient: false).ConfigureAwait(false); } [RunOn(TargetFrameworks.NetCore)] [TestCategory(TestCategories.Arlington)] public async Task ARLINGTON_ROPC_AAD_CCA_Async() { - var labResponse = await LabUserHelper.GetArlingtonUserAsync().ConfigureAwait(false); - await RunHappyPathTestAsync(labResponse, isPublicClient: false, cloud:Cloud.Arlington).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserArlington).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.ArlAppIdLabsApp).ConfigureAwait(false); + user.AzureEnvironment = LabConstants.AzureEnvironmentUsGovernment; + await RunHappyPathTestAsync(user, app, isPublicClient: false, cloud:Cloud.Arlington).ConfigureAwait(false); } [RunOn(TargetFrameworks.NetCore)] @@ -69,8 +73,9 @@ public async Task ARLINGTON_ROPC_AAD_CCA_Async() #endif public async Task ROPC_ADFSv4Federated_Async() { - var labResponse = await LabUserHelper.GetDefaultAdfsUserAsync().ConfigureAwait(false); - await RunHappyPathTestAsync(labResponse).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserFederated).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); + await RunHappyPathTestAsync(user, app).ConfigureAwait(false); } [RunOn(TargetFrameworks.NetCore)] @@ -80,14 +85,14 @@ public async Task ROPC_ADFSv4Federated_Async() #endif public async Task AcquireTokenFromAdfsUsernamePasswordAsync() { - LabResponse labResponse = await LabUserHelper.GetDefaultAdfsUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserFederated).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); - var user = labResponse.User; // Use the new ADFS authority and disable validation since ADFS infrastructure is not fully available Uri authorityUri = new Uri("https://fs.id4slab1.com/adfs"); var msalPublicClient = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithAuthority(authorityUri, validateAuthority: false) .WithTestLogging() .Build(); @@ -110,11 +115,12 @@ public async Task AcquireTokenFromAdfsUsernamePasswordAsync() [RunOn(TargetFrameworks.NetCore)] public async Task ROPC_B2C_Async() { - var labResponse = await LabUserHelper.GetB2CLocalAccountAsync().ConfigureAwait(false); - await RunB2CHappyPathTestAsync(labResponse).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserB2C).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.B2CAppIdLabsAppB2C).ConfigureAwait(false); + await RunB2CHappyPathTestAsync(user, app).ConfigureAwait(false); } - private async Task RunHappyPathTestAsync(LabResponse labResponse, string federationMetadata = "", bool isPublicClient = true, Cloud cloud = Cloud.Public) + private async Task RunHappyPathTestAsync(UserConfig user, AppConfig app, string federationMetadata = "", bool isPublicClient = true, Cloud cloud = Cloud.Public) { var factory = new HttpSnifferClientFactory(); IClientApplicationBase clientApp = null; @@ -122,10 +128,10 @@ private async Task RunHappyPathTestAsync(LabResponse labResponse, string federat if (isPublicClient) { clientApp = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithTestLogging() .WithHttpClientFactory(factory) - .WithAuthority(labResponse.Lab.Authority, "organizations") + .WithAuthority(app.Authority, "organizations") .Build(); } else @@ -135,7 +141,7 @@ private async Task RunHappyPathTestAsync(LabResponse labResponse, string federat .Create(settings.ClientId) .WithTestLogging() .WithHttpClientFactory(factory) - .WithAuthority(labResponse.Lab.Authority, "organizations"); + .WithAuthority(app.Authority, "organizations"); if (cloud == Cloud.Arlington) { @@ -151,13 +157,14 @@ private async Task RunHappyPathTestAsync(LabResponse labResponse, string federat AuthenticationResult authResult = await GetAuthenticationResultWithAssertAsync( - labResponse, + user, + app, factory, clientApp, federationMetadata, CorrelationId).ConfigureAwait(false); - if (AuthorityInfo.FromAuthorityUri(labResponse.Lab.Authority + "/" + labResponse.Lab.TenantId, false).AuthorityType == AuthorityType.Aad) + if (AuthorityInfo.FromAuthorityUri(app.Authority + "/" + user.TenantId, false).AuthorityType == AuthorityType.Aad) { AssertTenantProfiles(authResult.Account.GetTenantProfiles(), authResult.TenantId); } @@ -175,12 +182,12 @@ AuthenticationResult authResult // 4) After successful log-in, remove the password line you added in with step 1, and run the integration test again. } - private async Task RunB2CHappyPathTestAsync(LabResponse labResponse, string federationMetadata = "") + private async Task RunB2CHappyPathTestAsync(UserConfig user, AppConfig app, string federationMetadata = "") { var factory = new HttpSnifferClientFactory(); var msalPublicClient = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithB2CAuthority(B2CROPCAuthority) .WithTestLogging() .WithHttpClientFactory(factory) @@ -188,7 +195,7 @@ private async Task RunB2CHappyPathTestAsync(LabResponse labResponse, string fede #pragma warning disable CS0618 // Type or member is obsolete AuthenticationResult authResult = await msalPublicClient - .AcquireTokenByUsernamePassword(s_b2cScopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + .AcquireTokenByUsernamePassword(s_b2cScopes, user.Upn, user.GetOrFetchPassword()) .WithCorrelationId(CorrelationId) .WithFederationMetadata(federationMetadata) .ExecuteAsync(CancellationToken.None) @@ -219,7 +226,8 @@ private async Task RunB2CHappyPathTestAsync(LabResponse labResponse, string fede } private async Task GetAuthenticationResultWithAssertAsync( - LabResponse labResponse, + UserConfig user, + AppConfig app, HttpSnifferClientFactory factory, IClientApplicationBase clientApp, string federationMetadata, @@ -231,7 +239,7 @@ private async Task GetAuthenticationResultWithAssertAsync( { #pragma warning disable CS0618 // Type or member is obsolete authResult = await publicClientApp - .AcquireTokenByUsernamePassword(s_scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + .AcquireTokenByUsernamePassword(s_scopes, user.Upn, user.GetOrFetchPassword()) .WithCorrelationId(testCorrelationId) .WithFederationMetadata(federationMetadata) .ExecuteAsync(CancellationToken.None) @@ -241,7 +249,7 @@ private async Task GetAuthenticationResultWithAssertAsync( else { authResult = await (((IConfidentialClientApplication)clientApp) as IByUsernameAndPassword) - .AcquireTokenByUsernamePassword(s_scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword()) + .AcquireTokenByUsernamePassword(s_scopes, user.Upn, user.GetOrFetchPassword()) .WithCorrelationId(testCorrelationId) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); @@ -251,17 +259,17 @@ private async Task GetAuthenticationResultWithAssertAsync( Assert.AreEqual(TokenSource.IdentityProvider, authResult.AuthenticationResultMetadata.TokenSource); Assert.IsNotNull(authResult.AccessToken); Assert.IsNotNull(authResult.IdToken); - Assert.IsTrue(string.Equals(labResponse.User.Upn, authResult.Account.Username, StringComparison.InvariantCultureIgnoreCase)); - AssertTelemetryHeaders(factory, false, labResponse); - AssertCcsRoutingInformationIsSent(factory, labResponse); + Assert.IsTrue(string.Equals(user.Upn, authResult.Account.Username, StringComparison.InvariantCultureIgnoreCase)); + AssertTelemetryHeaders(factory, false, user, app); + AssertCcsRoutingInformationIsSent(factory, user); return authResult; } - private void AssertCcsRoutingInformationIsSent(HttpSnifferClientFactory factory, LabResponse labResponse) + private void AssertCcsRoutingInformationIsSent(HttpSnifferClientFactory factory, UserConfig user) { var CcsHeader = TestCommon.GetCcsHeaderFromSnifferFactory(factory); - Assert.AreEqual($"x-anchormailbox:upn:{labResponse.User.Upn}", $"{CcsHeader.Key}:{CcsHeader.Value.FirstOrDefault()}"); + Assert.AreEqual($"x-anchormailbox:upn:{user.Upn}", $"{CcsHeader.Key}:{CcsHeader.Value.FirstOrDefault()}"); } private void AssertCcsRoutingInformationIsNotSent(HttpSnifferClientFactory factory) @@ -284,10 +292,10 @@ private void AssertTenantProfiles(IEnumerable tenantProfiles, str Assert.IsNotNull(tenantProfile.ClaimsPrincipal.FindFirst(claim => claim.Type == "tid" && claim.Value == tenantId)); } - private void AssertTelemetryHeaders(HttpSnifferClientFactory factory, bool IsFailure, LabResponse labResponse) + private void AssertTelemetryHeaders(HttpSnifferClientFactory factory, bool IsFailure, UserConfig user, AppConfig app) { var (req, _) = factory.RequestsAndResponses.Single(x => - x.Item1.RequestUri.AbsoluteUri == labResponse.Lab.Authority + "organizations/oauth2/v2.0/token" && + x.Item1.RequestUri.AbsoluteUri == app.Authority + "organizations/oauth2/v2.0/token" && x.Item2.StatusCode == HttpStatusCode.OK); var telemetryCurrentValue = req.Headers.Single(h => h.Key == TelemetryConstants.XClientCurrentTelemetry).Value; diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/ConfidentialAppSettings.cs b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/ConfidentialAppSettings.cs index 5914476a9f..2862e5d6f0 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/ConfidentialAppSettings.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/ConfidentialAppSettings.cs @@ -67,12 +67,12 @@ private class PublicCloudConfidentialAppSettings : IConfidentialAppSettings private class AdfsConfidentialAppSettings : IConfidentialAppSettings { private const string AdfsCertName = "IDLABS-APP-Confidential-Client-Cert-OnPrem"; - private static readonly Lazy s_adfsLabResponse = new Lazy(() => + private static readonly Lazy s_adfsAppConfig = new Lazy(() => { - return LabUserHelper.GetDefaultAdfsUserAsync().GetAwaiter().GetResult(); + return LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).GetAwaiter().GetResult(); }); - public string ClientId => s_adfsLabResponse.Value.App.AppId; + public string ClientId => s_adfsAppConfig.Value.AppId; public string TenantId => ""; diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsalAssert.cs b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsalAssert.cs index 43e596fe6e..d38a5388bc 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsalAssert.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsalAssert.cs @@ -15,7 +15,7 @@ namespace Microsoft.Identity.Test.Integration.Infrastructure public static class MsalAssert { public static async Task AssertSingleAccountAsync( - LabResponse labResponse, + UserConfig labUser, IPublicClientApplication pca, AuthenticationResult result) { @@ -23,14 +23,14 @@ public static async Task AssertSingleAccountAsync( var account = (await pca.GetAccountsAsync().ConfigureAwait(false)).Single(); Assert.IsTrue( string.Equals( - labResponse.User.Upn, + labUser.Upn, result.Account.Username, System.StringComparison.InvariantCultureIgnoreCase)); return account; } - public static void AssertAuthResult(AuthenticationResult result, LabUser user = null) + public static void AssertAuthResult(AuthenticationResult result, UserConfig user = null) { Assert.IsNotNull(result); Assert.IsNotNull(result.AccessToken); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsiProxyHttpManager.cs b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsiProxyHttpManager.cs index e7cfd54dcf..3d3215b15b 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsiProxyHttpManager.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsiProxyHttpManager.cs @@ -29,6 +29,8 @@ internal class MsiProxyHttpManager : IHttpManager { private readonly string _testWebServiceEndpoint; private static HttpClient s_httpClient = new HttpClient(); + private static string s_cachedLabAccessAppId; + private static Azure.Core.AccessToken? s_cachedAccessToken; public MsiProxyHttpManager(string testWebServiceEndpoint) { @@ -51,9 +53,7 @@ public async Task SendRequestAsync( int retryCount = 0) { //Get token for the MSIHelperService - var labApi = new LabServiceApi(); - var token = await labApi.GetMSIHelperServiceTokenAsync() - .ConfigureAwait(false); + string token = await GetMSIHelperServiceTokenAsync().ConfigureAwait(false); //Add the Authorization header s_httpClient.DefaultRequestHeaders.Authorization = @@ -87,5 +87,23 @@ public async Task SendRequestAsync( return response; } + + private static async Task GetMSIHelperServiceTokenAsync() + { + if (s_cachedAccessToken == null || s_cachedAccessToken.Value.ExpiresOn <= DateTimeOffset.UtcNow.AddMinutes(5)) + { + if (s_cachedLabAccessAppId == null) + { + KeyVaultSecretsProvider keyVaultSecretsProvider = new KeyVaultSecretsProvider(); + s_cachedLabAccessAppId = keyVaultSecretsProvider.GetSecretByName("LabVaultAppID").Value; + } + + s_cachedAccessToken = await LabAuthenticationHelper + .GetAccessTokenForLabAPIAsync(s_cachedLabAccessAppId) + .ConfigureAwait(false); + } + + return s_cachedAccessToken.Value.Token; + } } } diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/PoPValidator.cs b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/PoPValidator.cs index e92822ddc7..dc4980ee53 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/PoPValidator.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/PoPValidator.cs @@ -20,7 +20,7 @@ public class PoPValidator private const string PoPValidatorEndpoint = "https://signedhttprequest.azurewebsites.net/api/validateSHR"; private static HttpClient s_httpClient = new HttpClient(); private static Lazy s_popValidationEndpointLazy = new Lazy( - () => LabUserHelper.KeyVaultSecretsProviderMsal.GetSecretByName( + () => LabResponseHelper.KeyVaultSecretsProviderMsal.GetSecretByName( "automation-pop-validation-endpoint", "841fc7c2ccdd48d7a9ef727e4ae84325").Value); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/SeleniumExtensions.cs b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/SeleniumExtensions.cs index 6be7688113..9fb7cc88d6 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/SeleniumExtensions.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/SeleniumExtensions.cs @@ -239,7 +239,7 @@ public static IWebElement FindElementById(this IWebDriver driver, string id) return driver.FindElement(By.Id(id)); } - public static void PerformLogin(this IWebDriver driver, LabUser user, Prompt prompt, bool withLoginHint = false, bool adfsOnly = false) + public static void PerformLogin(this IWebDriver driver, UserConfig user, Prompt prompt, bool withLoginHint = false, bool adfsOnly = false) { UserInformationFieldIds fields = new UserInformationFieldIds(user); @@ -284,7 +284,7 @@ private static void HandleStaySignedIn(IWebDriver driver) } } - private static void HandleConsent(IWebDriver driver, LabUser user, UserInformationFieldIds fields, Prompt prompt) + private static void HandleConsent(IWebDriver driver, UserConfig user, UserInformationFieldIds fields, Prompt prompt) { // For MSA, a special consent screen seems to come up every now and then if (user.Upn.Contains("outlook.com")) @@ -311,7 +311,7 @@ private static void HandleConsent(IWebDriver driver, LabUser user, UserInformati } } - private static void EnterPassword(IWebDriver driver, LabUser user, UserInformationFieldIds fields) + private static void EnterPassword(IWebDriver driver, UserConfig user, UserInformationFieldIds fields) { Trace.WriteLine("Logging in ... Entering password"); string password = user.GetOrFetchPassword(); @@ -322,7 +322,7 @@ private static void EnterPassword(IWebDriver driver, LabUser user, UserInformati driver.WaitForElementToBeVisibleAndEnabled(By.Id(fields.GetPasswordSignInButtonId())).Click(); } - private static void EnterUsername(IWebDriver driver, LabUser user, bool withLoginHint, bool adfsOnly, UserInformationFieldIds fields) + private static void EnterUsername(IWebDriver driver, UserConfig user, bool withLoginHint, bool adfsOnly, UserInformationFieldIds fields) { if (adfsOnly && !withLoginHint) { @@ -354,7 +354,7 @@ private static void EnterUsername(IWebDriver driver, LabUser user, bool withLogi public static void PerformDeviceCodeLogin( DeviceCodeResult deviceCodeResult, - LabUser user, + UserConfig user, TestContext testContext, bool isAdfs = false) { diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/UserInformationFieldIds.cs b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/UserInformationFieldIds.cs index 1cb6d359f6..d265214566 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/UserInformationFieldIds.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/UserInformationFieldIds.cs @@ -8,11 +8,11 @@ namespace Microsoft.Identity.Test.Integration.Infrastructure { public class UserInformationFieldIds { - private readonly LabUser _user; + private readonly UserConfig _user; private string _passwordInputId; private string _passwordSignInButtonId; - public UserInformationFieldIds(LabUser user) + public UserInformationFieldIds(UserConfig user) { _user = user; } @@ -64,14 +64,14 @@ public string AADUsernameInputId private void DetermineFieldIds() { - if (_user.UserType == UserType.Federated) + if (_user.UserType == LabConstants.UserTypeFederated) { _passwordInputId = CoreUiTestConstants.AdfsV4WebPasswordId; _passwordSignInButtonId = CoreUiTestConstants.AdfsV4WebSubmitId; return; } - if (_user.UserType == UserType.B2C) + if (_user.UserType == LabConstants.UserTypeB2C) { DetermineB2CFieldIds(); return; @@ -85,15 +85,15 @@ private void DetermineB2CFieldIds() { switch (_user.B2cProvider) { - case B2CIdentityProvider.Local: + case LabConstants.B2CIdentityProviderLocal: _passwordInputId = CoreUiTestConstants.B2CWebPasswordId; _passwordSignInButtonId = CoreUiTestConstants.B2CWebSubmitId; break; - case B2CIdentityProvider.Facebook: + case LabConstants.B2CIdentityProviderFacebook: _passwordInputId = CoreUiTestConstants.B2CWebPasswordFacebookId; _passwordSignInButtonId = CoreUiTestConstants.B2CFacebookSubmitId; break; - case B2CIdentityProvider.Google: + case LabConstants.B2CIdentityProviderGoogle: _passwordInputId = CoreUiTestConstants.B2CWebPasswordGoogleId; _passwordSignInButtonId = CoreUiTestConstants.B2CGoogleSignInId; break; diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/ConfidentialClientAuthorizationTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/ConfidentialClientAuthorizationTests.cs index a12fd10608..659d2375ee 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/ConfidentialClientAuthorizationTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/ConfidentialClientAuthorizationTests.cs @@ -61,28 +61,31 @@ public void TestInitialize() public async Task SeleniumGetAuthCode_RedeemForAt_CommonAuthority_Async() { // Arrange - LabResponse labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); - await RunTestForUserAsync(labResponse.App.AppId, labResponse, "https://login.microsoftonline.com/common", false).ConfigureAwait(false); - await RunTestForUserAsync(labResponse.App.AppId, labResponse, $"https://login.microsoftonline.com/{labResponse.User.TenantId}", false).ConfigureAwait(false); + await RunTestForUserAsync(app.AppId, user, "https://login.microsoftonline.com/common", false).ConfigureAwait(false); + await RunTestForUserAsync(app.AppId, user, $"https://login.microsoftonline.com/{user.TenantId}", false).ConfigureAwait(false); } [TestMethod] public async Task GetTokenByAuthCode_WithPKCE_Async() { // Arrange - LabResponse labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - await RunTestForUserAsync(labResponse.App.AppId, labResponse, "https://login.microsoftonline.com/common", true).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); + await RunTestForUserAsync(app.AppId, user, "https://login.microsoftonline.com/common", true).ConfigureAwait(false); } [TestMethod] public async Task GetTokenByAuthCode_HybridSPA_Async() { // Arrange - LabResponse labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); - var result = await RunTestForUserAsync(labResponse.App.AppId, labResponse, - $"https://login.microsoftonline.com/{labResponse.User.TenantId}", false).ConfigureAwait(false); + var result = await RunTestForUserAsync(app.AppId, user, + $"https://login.microsoftonline.com/{user.TenantId}", false).ConfigureAwait(false); Assert.IsNotNull(result.SpaAuthCode); @@ -93,7 +96,7 @@ public async Task GetTokenByAuthCode_HybridSPA_Async() //Assert.IsNull(result.SpaAuthCode); } - private async Task RunTestForUserAsync(string appId, LabResponse labResponse, + private async Task RunTestForUserAsync(string appId, UserConfig user, string authority, bool usePkce = false, string redirectUri = null, bool spaCode = true) { var cert = await s_secretProvider.GetCertificateWithPrivateMaterialAsync( @@ -130,7 +133,7 @@ private async Task RunTestForUserAsync(string appId, LabRe var seleniumUi = new SeleniumWebUI((driver) => { Trace.WriteLine("Starting Selenium automation"); - driver.PerformLogin(labResponse.User, Prompt.SelectAccount, false, false); + driver.PerformLogin(user, Prompt.SelectAccount, false, false); }, TestContext); CancellationTokenSource cts = new CancellationTokenSource(s_timeout); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/DeviceCodeFlowIntegrationTest.cs b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/DeviceCodeFlowIntegrationTest.cs index 172ab1a95a..28b9ecaece 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/DeviceCodeFlowIntegrationTest.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/DeviceCodeFlowIntegrationTest.cs @@ -39,27 +39,29 @@ public class DeviceCodeFlow [Timeout(2 * 60 * 1000)] // 2 min timeout public async Task DeviceCodeFlowTestAsync() { - LabResponse labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - await AcquireTokenWithDeviceCodeFlowAsync(labResponse, "aad user").ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgsPublicClient).ConfigureAwait(false); + await AcquireTokenWithDeviceCodeFlowAsync(user, app, "aad user").ConfigureAwait(false); } [TestMethod] [Timeout(2 * 60 * 1000)] // 2 min timeout public async Task SilentTokenAfterDeviceCodeFlowWithBrokerTestAsync() { - LabResponse labResponse = await LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().ConfigureAwait(false); - await AcquireTokenSilentAfterDeviceCodeFlowWithBrokerAsync(labResponse, "aad user").ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).ConfigureAwait(false); + await AcquireTokenSilentAfterDeviceCodeFlowWithBrokerAsync(user, app, "aad user").ConfigureAwait(false); } - private async Task AcquireTokenWithDeviceCodeFlowAsync(LabResponse labResponse, string userType) + private async Task AcquireTokenWithDeviceCodeFlowAsync(UserConfig user, AppConfig app, string userType) { Trace.WriteLine($"Calling AcquireTokenWithDeviceCodeAsync with {0}", userType); - var builder = PublicClientApplicationBuilder.Create(labResponse.App.AppId).WithTestLogging(); + var builder = PublicClientApplicationBuilder.Create(app.AppId).WithTestLogging(); - switch (labResponse.User.AzureEnvironment) + switch (user.AzureEnvironment) { - case AzureEnvironment.azureusgovernment: - builder.WithAuthority(labResponse.Lab.Authority + labResponse.Lab.TenantId); + case LabConstants.AzureEnvironmentUsGovernment: + builder.WithAuthority(app.Authority + user.TenantId); break; default: break; @@ -70,7 +72,7 @@ private async Task AcquireTokenWithDeviceCodeFlowAsync(LabResponse labResponse, var result = await pca.AcquireTokenWithDeviceCode(s_scopes, deviceCodeResult => { - SeleniumExtensions.PerformDeviceCodeLogin(deviceCodeResult, labResponse.User, TestContext, false); + SeleniumExtensions.PerformDeviceCodeLogin(deviceCodeResult, user, TestContext, false); return Task.FromResult(0); }).ExecuteAsync(CancellationToken.None).ConfigureAwait(false); @@ -83,16 +85,16 @@ private async Task AcquireTokenWithDeviceCodeFlowAsync(LabResponse labResponse, Assert.IsTrue(!string.IsNullOrEmpty(result.AccessToken)); } - private async Task AcquireTokenSilentAfterDeviceCodeFlowWithBrokerAsync(LabResponse labResponse, string userType) + private async Task AcquireTokenSilentAfterDeviceCodeFlowWithBrokerAsync(UserConfig user, AppConfig app, string userType) { Trace.WriteLine($"Calling AcquireTokenSilentAfterDeviceCodeFlowWithBrokerAsync with {0}", userType); BrokerOptions options = TestUtils.GetPlatformBroker(); - var builder = PublicClientApplicationBuilder.Create(labResponse.App.AppId).WithTestLogging().WithBroker(options); + var builder = PublicClientApplicationBuilder.Create(app.AppId).WithTestLogging().WithBroker(options); - switch (labResponse.User.AzureEnvironment) + switch (user.AzureEnvironment) { - case AzureEnvironment.azureusgovernment: - builder.WithAuthority(labResponse.Lab.Authority + labResponse.Lab.TenantId); + case LabConstants.AzureEnvironmentUsGovernment: + builder.WithAuthority(app.Authority + user.TenantId); break; default: break; @@ -103,7 +105,7 @@ private async Task AcquireTokenSilentAfterDeviceCodeFlowWithBrokerAsync(LabRespo var result = await pca.AcquireTokenWithDeviceCode(s_scopes, deviceCodeResult => { - SeleniumExtensions.PerformDeviceCodeLogin(deviceCodeResult, labResponse.User, TestContext, false); + SeleniumExtensions.PerformDeviceCodeLogin(deviceCodeResult, user, TestContext, false); return Task.FromResult(0); }).ExecuteAsync(CancellationToken.None).ConfigureAwait(false); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/FociTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/FociTests.cs index ebd72d706f..16dc4485c3 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/FociTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/FociTests.cs @@ -45,15 +45,15 @@ public void TestInitialize() [TestMethod] public async Task FociSignInSignOutAsync() { - LabResponse labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); - LabUser user = labResponse.User; + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); string cacheFilePath = null; try { cacheFilePath = Path.GetTempFileName(); - CreateFamilyApps(labResponse, cacheFilePath, out IPublicClientApplication pca_fam1, out IPublicClientApplication pca_fam2, out IPublicClientApplication pca_nonFam); + CreateFamilyApps(app.AppId, cacheFilePath, out IPublicClientApplication pca_fam1, out IPublicClientApplication pca_fam2, out IPublicClientApplication pca_nonFam); var userCacheAccess1 = pca_fam1.UserTokenCache.RecordAccess(); var userCacheAccess2 = pca_fam2.UserTokenCache.RecordAccess(); @@ -64,7 +64,7 @@ public async Task FociSignInSignOutAsync() { SeleniumExtensions.PerformDeviceCodeLogin( deviceCodeResult, - labResponse.User, + user, TestContext, false); @@ -112,7 +112,7 @@ await AssertException.TaskThrowsAsync(() => pca_nonFam } } - private static void CreateFamilyApps(LabResponse labResponse, string cacheFilePath, out IPublicClientApplication pca_fam1, out IPublicClientApplication pca_fam2, out IPublicClientApplication pca_nonFam) + private static void CreateFamilyApps(string nonFamilyAppId, string cacheFilePath, out IPublicClientApplication pca_fam1, out IPublicClientApplication pca_fam2, out IPublicClientApplication pca_nonFam) { var keyvault = new KeyVaultSecretsProvider(KeyVaultInstance.MsalTeam); var clientId1 = "872cd9fa-d31f-45e0-9eab-6e460a02d1f1"; @@ -129,7 +129,7 @@ private static void CreateFamilyApps(LabResponse labResponse, string cacheFilePa .Build(); pca_nonFam = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(nonFamilyAppId) .WithTestLogging() .Build(); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/InteractiveFlowTests.NetFwk.cs b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/InteractiveFlowTests.NetFwk.cs index c71dd11577..7896195995 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/InteractiveFlowTests.NetFwk.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/InteractiveFlowTests.NetFwk.cs @@ -43,8 +43,9 @@ public void TestInitialize() public async Task Interactive_AADAsync() { // Arrange - Use pure public client multi-tenant app to avoid AADSTS7000218 credential requirement - LabResponse labResponse = await LabUserHelper.MergeKVLabDataAsync("MSAL-User-Default-JSON", "ID4SLAB1", "MSAL-APP-AzureADMultipleOrgsPC-JSON").ConfigureAwait(false); - var result = await RunTestForUserAsync(labResponse).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgsPublicClient).ConfigureAwait(false); + var result = await RunTestForUserAsync(user, app).ConfigureAwait(false); } [RunOn(TargetFrameworks.NetCore)] @@ -52,17 +53,20 @@ public async Task Interactive_AADAsync() public async Task Arlington_Interactive_AADAsync() { // Arrange - LabResponse labResponse = await LabUserHelper.GetArlingtonUserAsync().ConfigureAwait(false); - await RunTestForUserAsync(labResponse, false).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserArlington).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.ArlAppIdLabsApp).ConfigureAwait(false); + user.AzureEnvironment = LabConstants.AzureEnvironmentUsGovernment; + await RunTestForUserAsync(user, app, false).ConfigureAwait(false); } [RunOn(TargetFrameworks.NetCore)] public async Task InteractiveConsentPromptAsync() { - LabResponse labResponse = await LabUserHelper.MergeKVLabDataAsync("MSAL-User-Default-JSON", "ID4SLAB1", "MSAL-APP-AzureADMultipleOrgsPC-JSON").ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgsPublicClient).ConfigureAwait(false); - await RunPromptTestForUserAsync(labResponse, Prompt.Consent, true).ConfigureAwait(false); - await RunPromptTestForUserAsync(labResponse, Prompt.Consent, false).ConfigureAwait(false); + await RunPromptTestForUserAsync(user, app, Prompt.Consent, true).ConfigureAwait(false); + await RunPromptTestForUserAsync(user, app, Prompt.Consent, false).ConfigureAwait(false); } [RunOn(TargetFrameworks.NetCore)] @@ -71,28 +75,21 @@ public async Task InteractiveConsentPromptAsync() #endif public async Task Interactive_Adfs_FederatedAsync() { - LabResponse labResponse = await LabUserHelper.GetDefaultAdfsUserAsync().ConfigureAwait(false); - await RunTestForUserAsync(labResponse).ConfigureAwait(false); - } - - [RunOn(TargetFrameworks.NetCore)] - [TestCategory(TestCategories.Arlington)] -#if IGNORE_FEDERATED - [Ignore] -#endif - public async Task Arlington_Interactive_AdfsV2019_FederatedAsync() - { - LabResponse labResponse = await LabUserHelper.GetArlingtonADFSUserAsync().ConfigureAwait(false); - await RunTestForUserAsync(labResponse, false).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserFederated).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); + await RunTestForUserAsync(user, app).ConfigureAwait(false); } [RunOn(TargetFrameworks.NetCore)] public async Task Interactive_Arlington_MultiCloudSupport_AADAsync() { // Arrange - LabResponse labResponse = await LabUserHelper.GetArlingtonUserAsync().ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserArlington).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.ArlAppIdLabsApp).ConfigureAwait(false); + user.AzureEnvironment = LabConstants.AzureEnvironmentUsGovernment; + IPublicClientApplication pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri()) .WithAuthority("https://login.microsoftonline.com/common") .WithMultiCloudSupport(true) @@ -102,7 +99,7 @@ public async Task Interactive_Arlington_MultiCloudSupport_AADAsync() Trace.WriteLine("Part 1 - Acquire a token interactively"); AuthenticationResult result = await pca .AcquireTokenInteractive(s_scopes) - .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.SelectAccount, false)) + .WithCustomWebUi(CreateSeleniumCustomWebUI(user, Prompt.SelectAccount, false)) .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token) .ConfigureAwait(false); @@ -110,8 +107,8 @@ public async Task Interactive_Arlington_MultiCloudSupport_AADAsync() Assert.IsNotNull(result.Account); Assert.IsNotNull(result.Account.GetTenantProfiles()); Assert.IsTrue(result.Account.GetTenantProfiles().Any()); - Assert.AreEqual(labResponse.User.Upn, result.Account.Username); - Assert.IsTrue(labResponse.Lab.Authority.Contains(result.Account.Environment)); + Assert.AreEqual(user.Upn, result.Account.Username); + Assert.IsTrue(app.Authority.Contains(result.Account.Environment)); Trace.WriteLine("Part 2 - Get Accounts"); var accounts = await pca.GetAccountsAsync().ConfigureAwait(false); @@ -123,7 +120,7 @@ public async Task Interactive_Arlington_MultiCloudSupport_AADAsync() Assert.IsNotNull(account.GetTenantProfiles()); Assert.IsTrue(account.GetTenantProfiles().Any()); - Assert.AreEqual(labResponse.User.Upn, account.Username); + Assert.AreEqual(user.Upn, account.Username); Assert.AreEqual("login.microsoftonline.us", account.Environment); Trace.WriteLine("Part 3 - Acquire a token silently"); @@ -136,7 +133,7 @@ public async Task Interactive_Arlington_MultiCloudSupport_AADAsync() Assert.IsNotNull(result.Account); Assert.IsNotNull(result.Account.GetTenantProfiles()); Assert.IsTrue(result.Account.GetTenantProfiles().Any()); - Assert.IsTrue(labResponse.Lab.Authority.Contains(result.Account.Environment)); + Assert.IsTrue(app.Authority.Contains(result.Account.Environment)); } [RunOn(TargetFrameworks.NetCore)] @@ -146,17 +143,19 @@ public async Task Interactive_Arlington_MultiCloudSupport_AADAsync() #endif public async Task Interactive_Adfs_DirectAsync() { - LabResponse labResponse = await LabUserHelper.GetDefaultAdfsUserAsync().ConfigureAwait(false); - await RunTestForUserAsync(labResponse, true).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserFederated).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false); + await RunTestForUserAsync(user, app, true).ConfigureAwait(false); } [RunOn(TargetFrameworks.NetCore)] public async Task ValidateCcsHeadersForInteractiveAuthCodeFlowAsync() { - LabResponse labResponse = await LabUserHelper.MergeKVLabDataAsync("MSAL-User-Default-JSON", "ID4SLAB1", "MSAL-APP-AzureADMultipleOrgsPC-JSON").ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgsPublicClient).ConfigureAwait(false); var pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithDefaultRedirectUri() .WithRedirectUri("http://localhost:52073") .WithTestLogging(out HttpSnifferClientFactory factory) @@ -165,13 +164,13 @@ public async Task ValidateCcsHeadersForInteractiveAuthCodeFlowAsync() AuthenticationResult authResult = await pca .AcquireTokenInteractive(s_scopes) .WithPrompt(Prompt.SelectAccount) - .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.SelectAccount)) + .WithCustomWebUi(CreateSeleniumCustomWebUI(user, Prompt.SelectAccount)) .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token) .ConfigureAwait(false); var CcsHeader = TestCommon.GetCcsHeaderFromSnifferFactory(factory); - var userObjectId = labResponse.User.ObjectId; - var userTenantID = labResponse.User.TenantId; + var userObjectId = user.ObjectId; + var userTenantID = user.TenantId; Assert.AreEqual($"x-anchormailbox:oid:{userObjectId}@{userTenantID}", $"{CcsHeader.Key}:{CcsHeader.Value.FirstOrDefault()}"); Assert.IsNotNull(authResult); @@ -208,14 +207,14 @@ public async Task Interactive_GenericAuthority_DuendeDemoInstanceAsync() Assert.AreEqual("Bearer", authResult.TokenType); } - private async Task RunTestForUserAsync(LabResponse labResponse, bool directToAdfs = false) + private async Task RunTestForUserAsync(UserConfig user, AppConfig app, bool directToAdfs = false) { HttpSnifferClientFactory factory = null; IPublicClientApplication pca; if (directToAdfs) { pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithRedirectUri("http://localhost:52073") .WithAdfsAuthority("https://fs.id4slab1.com/adfs", validateAuthority: false) .WithTestLogging() @@ -224,9 +223,9 @@ private async Task RunTestForUserAsync(LabResponse labResp else { pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithRedirectUri("http://localhost:52073") - .WithAuthority(labResponse.Lab.Authority + "common") + .WithAuthority(app.Authority + "common") .WithTestLogging(out factory) .Build(); } @@ -236,7 +235,7 @@ private async Task RunTestForUserAsync(LabResponse labResp Trace.WriteLine("Part 1 - Acquire a token interactively, no login hint"); AuthenticationResult result = await pca .AcquireTokenInteractive(s_scopes) - .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.SelectAccount, false, directToAdfs)) + .WithCustomWebUi(CreateSeleniumCustomWebUI(user, Prompt.SelectAccount, false, directToAdfs)) .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token) .ConfigureAwait(false); @@ -244,7 +243,7 @@ private async Task RunTestForUserAsync(LabResponse labResp Assert.IsTrue(result.AuthenticationResultMetadata.DurationInHttpInMs > 0); userCacheAccess.AssertAccessCounts(0, 1); - IAccount account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); + IAccount account = await MsalAssert.AssertSingleAccountAsync(user, pca, result).ConfigureAwait(false); userCacheAccess.AssertAccessCounts(1, 1); // the assert calls GetAccounts Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache); @@ -264,15 +263,15 @@ private async Task RunTestForUserAsync(LabResponse labResp Trace.WriteLine("Part 3 - Acquire a token interactively again, with login hint"); result = await pca .AcquireTokenInteractive(s_scopes) - .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.ForceLogin, true, directToAdfs)) + .WithCustomWebUi(CreateSeleniumCustomWebUI(user, Prompt.ForceLogin, true, directToAdfs)) .WithPrompt(Prompt.ForceLogin) - .WithLoginHint(labResponse.User.Upn) + .WithLoginHint(user.Upn) .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token) .ConfigureAwait(false); userCacheAccess.AssertAccessCounts(2, 3); - AssertCcsRoutingInformationIsSent(factory, labResponse); + AssertCcsRoutingInformationIsSent(factory, user); - account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); + account = await MsalAssert.AssertSingleAccountAsync(user, pca, result).ConfigureAwait(false); userCacheAccess.AssertAccessCounts(3, 3); Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache); @@ -294,16 +293,16 @@ private async Task RunTestForUserAsync(LabResponse labResp .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); - await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); + await MsalAssert.AssertSingleAccountAsync(user, pca, result).ConfigureAwait(false); Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache); - AssertCcsRoutingInformationIsSent(factory, labResponse); + AssertCcsRoutingInformationIsSent(factory, user); return result; } - private void AssertCcsRoutingInformationIsSent(HttpSnifferClientFactory factory, LabResponse labResponse) + private void AssertCcsRoutingInformationIsSent(HttpSnifferClientFactory factory, UserConfig user) { - if (labResponse.User.FederationProvider != FederationProvider.None) + if (user.FederationProvider != LabConstants.FederationProviderNone) { return; } @@ -312,29 +311,29 @@ private void AssertCcsRoutingInformationIsSent(HttpSnifferClientFactory factory, if (!String.IsNullOrEmpty(CcsHeader.Value?.FirstOrDefault())) { - ValidateCcsHeader(CcsHeader, labResponse); + ValidateCcsHeader(CcsHeader, user); } } - private void ValidateCcsHeader(KeyValuePair> CcsHeader, LabResponse labResponse) + private void ValidateCcsHeader(KeyValuePair> CcsHeader, UserConfig user) { var ccsHeaderValue = CcsHeader.Value.FirstOrDefault(); if (ccsHeaderValue.Contains("upn")) { - Assert.AreEqual($"X-AnchorMailbox:UPN:{labResponse.User.Upn}", $"{CcsHeader.Key}:{ccsHeaderValue}"); + Assert.AreEqual($"X-AnchorMailbox:UPN:{user.Upn}", $"{CcsHeader.Key}:{ccsHeaderValue}"); } else { - var userObjectId = labResponse.User.ObjectId; - var userTenantID = labResponse.User.TenantId; + var userObjectId = user.ObjectId; + var userTenantID = user.TenantId; Assert.AreEqual($"X-AnchorMailbox:Oid:{userObjectId}@{userTenantID}", $"{CcsHeader.Key}:{ccsHeaderValue}"); } } - private async Task RunPromptTestForUserAsync(LabResponse labResponse, Prompt prompt, bool useLoginHint) + private async Task RunPromptTestForUserAsync(UserConfig user, AppConfig app, Prompt prompt, bool useLoginHint) { var pca = PublicClientApplicationBuilder - .Create(labResponse.App.AppId) + .Create(app.AppId) .WithDefaultRedirectUri() .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri()) .WithTestLogging() @@ -343,21 +342,21 @@ private async Task RunPromptTestForUserAsync(LabResponse labResponse, Prompt pro AcquireTokenInteractiveParameterBuilder builder = pca .AcquireTokenInteractive(s_scopes) .WithPrompt(prompt) - .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, prompt, useLoginHint)); + .WithCustomWebUi(CreateSeleniumCustomWebUI(user, prompt, useLoginHint)); if (useLoginHint) { - builder = builder.WithLoginHint(labResponse.User.Upn); + builder = builder.WithLoginHint(user.Upn); } AuthenticationResult result = await builder .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token) .ConfigureAwait(false); - await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); + await MsalAssert.AssertSingleAccountAsync(user, pca, result).ConfigureAwait(false); } - private SeleniumWebUI CreateSeleniumCustomWebUI(LabUser user, Prompt prompt, bool withLoginHint = false, bool adfsOnly = false) + private SeleniumWebUI CreateSeleniumCustomWebUI(UserConfig user, Prompt prompt, bool withLoginHint = false, bool adfsOnly = false) { return new SeleniumWebUI((driver) => { diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/SSHCertificateTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/SSHCertificateTests.cs index 2b49e4ed2a..4d90f7bd39 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/SSHCertificateTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/SSHCertificateTests.cs @@ -35,11 +35,11 @@ public class SSHCertTests [TestMethod] public async Task Interactive_SSHCert_Async() { - LabResponse labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false); - await CreateSSHCertTestAsync(labResponse).ConfigureAwait(false); + var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); + await CreateSSHCertTestAsync(user).ConfigureAwait(false); } - private async Task CreateSSHCertTestAsync(LabResponse labResponse) + private async Task CreateSSHCertTestAsync(UserConfig user) { IPublicClientApplication pca = PublicClientApplicationBuilder .Create(_SSH_ClientId) @@ -54,14 +54,14 @@ private async Task CreateSSHCertTestAsync(LabResponse labResponse) AuthenticationResult result = await pca .AcquireTokenInteractive(_SSH_scopes) - .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.ForceLogin)) + .WithCustomWebUi(CreateSeleniumCustomWebUI(user, Prompt.ForceLogin)) .WithSSHCertificateAuthenticationScheme(jwk, "key1") .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token) .ConfigureAwait(false); userCacheAccess.AssertAccessCounts(0, 1); Assert.AreEqual("ssh-cert", result.TokenType); - IAccount account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); + IAccount account = await MsalAssert.AssertSingleAccountAsync(user, pca, result).ConfigureAwait(false); userCacheAccess.AssertAccessCounts(1, 1); // the assert calls GetAccounts Trace.WriteLine("Part 2 - Acquire a token silent with the same keyID - should be served from the cache"); @@ -72,7 +72,7 @@ private async Task CreateSSHCertTestAsync(LabResponse labResponse) .ConfigureAwait(false); userCacheAccess.AssertAccessCounts(2, 1); - account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); + account = await MsalAssert.AssertSingleAccountAsync(user, pca, result).ConfigureAwait(false); userCacheAccess.AssertAccessCounts(3, 1); Trace.WriteLine("Part 3 - Acquire a token silent with a different keyID - should not sbe served from the cache"); @@ -84,7 +84,7 @@ private async Task CreateSSHCertTestAsync(LabResponse labResponse) Assert.AreEqual("ssh-cert", result.TokenType); userCacheAccess.AssertAccessCounts(4, 2); - await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); + await MsalAssert.AssertSingleAccountAsync(user, pca, result).ConfigureAwait(false); } private string CreateJwk() @@ -99,7 +99,7 @@ private string CreateJwk() return jwk; } - private SeleniumWebUI CreateSeleniumCustomWebUI(LabUser user, Prompt prompt, bool withLoginHint = false, bool adfsOnly = false) + private SeleniumWebUI CreateSeleniumCustomWebUI(UserConfig user, Prompt prompt, bool withLoginHint = false, bool adfsOnly = false) { return new SeleniumWebUI((driver) => { diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/AppConfig.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/AppConfig.cs new file mode 100644 index 0000000000..1327fc0bfa --- /dev/null +++ b/tests/Microsoft.Identity.Test.LabInfrastructure/AppConfig.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Newtonsoft.Json; + +namespace Microsoft.Identity.Test.LabInfrastructure +{ + /// + /// Represents application configuration retrieved from Key Vault. + /// + public class AppConfig + { + [JsonProperty("appid")] + public string AppId { get; set; } + + [JsonProperty("redirecturi")] + public string RedirectUri { get; set; } + + [JsonProperty("authority")] + public string Authority { get; set; } + + [JsonProperty("defaultscopes")] + public string DefaultScopes { get; set; } + } +} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecrets.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecrets.cs new file mode 100644 index 0000000000..645bc70cd9 --- /dev/null +++ b/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecrets.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Identity.Test.LabInfrastructure +{ + /// + /// Contains names of secrets stored in Azure Key Vault for lab configuration. + /// These secrets contain JSON-serialized configuration objects for users, apps, and lab environments. + /// + public static class KeyVaultSecrets + { + // Names of key vault secrets for user configuration JSONs + public const string UserPublicCloud = "User-PublicCloud-Config"; + public const string UserFederated = "User-Federated-Config"; + public const string UserPublicCloud2 = "MSAL-User-Default2-JSON"; + public const string UserXcg = "MSAL-User-XCG-JSON"; + public const string UserB2C = "MSAL-USER-B2C-JSON"; + public const string UserArlington = "MSAL-USER-Arlington-JSON"; + public const string UserCiam = "MSAL-USER-CIAM-JSON"; + public const string UserPop = "MSAL-User-POP-JSON"; + + // Names of key vault secrets for application configuration JSONs + public const string AppPCAClient = "App-PCAClient-Config"; + public const string MsalAppAzureAdMultipleOrgs = "MSAL-APP-AzureADMultipleOrgs-JSON"; + public const string MsalAppAzureAdMultipleOrgsPublicClient = "MSAL-APP-AzureADMultipleOrgsPC-JSON"; + public const string B2CAppIdLabsAppB2C = "MSAL-App-B2C-JSON"; + public const string ArlAppIdLabsApp = "MSAL-App-Arlington-JSON"; + public const string MsalAppCiam = "MSAL-App-CIAM-JSON"; + + // Other configuration secrets + public const string EnvVariablesMsiConfig = "EnvVariables-MSI-Config"; + } +} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecretsProvider.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecretsProvider.cs index 0079f2162d..fc6c1f7d94 100644 --- a/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecretsProvider.cs +++ b/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecretsProvider.cs @@ -13,13 +13,12 @@ namespace Microsoft.Identity.Test.LabInfrastructure public class KeyVaultInstance { /// - /// The KeyVault maintained by the MSID. It is recommended for use. + /// This Key Vault is generally used for frequently rotated credentials and other sensitive configuration. /// public const string MSIDLab = "https://msidlabs.vault.azure.net"; /// - /// The KeyVault maintained by the MSAL.NET team and have full control over. - /// Should be used temporarily - secrets should be stored and managed by MSID Lab. + /// This KeyVault is generally used for static user/app/etc. info and other low-risk configuration. /// public const string MsalTeam = "https://id4skeyvault.vault.azure.net/"; } diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabApiConstants.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabApiConstants.cs deleted file mode 100644 index 14338c9e2e..0000000000 --- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabApiConstants.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Microsoft.Identity.Test.LabInfrastructure -{ - public class LabApiConstants - { - // constants for Lab api - public const string MobileDeviceManagementWithConditionalAccess = "mdmca"; - public const string MobileAppManagementWithConditionalAccess = "mamca"; - public const string MobileAppManagement = "mam"; - public const string MultiFactorAuthentication = "mfa"; - public const string License = "license"; - public const string FederationProvider = "federationProvider"; - public const string FederatedUser = "isFederated"; - public const string UserType = "usertype"; - public const string External = "external"; - public const string B2CProvider = "b2cProvider"; - public const string B2CLocal = "local"; - public const string B2CFacebook = "facebook"; - public const string B2CGoogle = "google"; - public const string B2CMSA = "msa"; - public const string UserContains = "usercontains"; - public const string AppName = "AppName"; - public const string MSAOutlookAccount = "MSIDLAB4_Outlook"; - public const string MSAOutlookAccountClientID = "9668f2bd-6103-4292-9024-84fa2d1b6fb2"; - public const string Upn = "upn"; - - // constants for V2 Lab api - public const string ProtectionPolicy = "protectionpolicy"; - public const string HomeDomain = "homedomain"; - public const string HomeUPN = "homeupn"; - public const string FederationProviderV2 = "federationprovider"; - public const string AzureEnvironment = "azureenvironment"; - public const string SignInAudience = "SignInAudience"; - public const string AppPlatform = "appplatform"; - public const string PublicClient = "publicclient"; - - public const string True = "true"; - public const string False = "false"; - - public const string LabEndPoint = "https://msidlab.com/api/user"; - public const string LabUserCredentialEndpoint = "https://msidlab.com/api/LabSecret"; - public const string LabAppEndpoint = "https://msidlab.com/api/app/"; - public const string LabInfoEndpoint = "https://msidlab.com/api/Lab/"; - } -} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabConstants.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabConstants.cs new file mode 100644 index 0000000000..3e14f69548 --- /dev/null +++ b/tests/Microsoft.Identity.Test.LabInfrastructure/LabConstants.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Identity.Test.LabInfrastructure +{ + /// + /// Constants for lab user configuration values used in testing. + /// + public static class LabConstants + { + // FederationProvider values + public const string FederationProviderNone = "None"; + + // B2CIdentityProvider values + public const string B2CIdentityProviderLocal = "Local"; + public const string B2CIdentityProviderFacebook = "Facebook"; + public const string B2CIdentityProviderGoogle = "Google"; + + // UserType values + public const string UserTypeB2C = "B2C"; + public const string UserTypeFederated = "Federated"; + public const string UserTypeMSA = "MSA"; + + // AzureEnvironment values + public const string AzureEnvironmentUsGovernment = "azureusgovernment"; + } +} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabResponse.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabResponse.cs deleted file mode 100644 index 14dcc75470..0000000000 --- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabResponse.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Newtonsoft.Json; - -namespace Microsoft.Identity.Test.LabInfrastructure -{ - public class LabResponse - { - [JsonProperty("app")] - public LabApp App { get; set; } - - [JsonProperty("user")] - public LabUser User { get; set; } - - [JsonProperty("lab")] - public Lab Lab { get; set; } - } - - public class LabApp - { - [JsonProperty("appid")] - public string AppId { get; set; } - - // TODO: this is a list, but lab sends a string. Not used today, discuss with lab to return a list - [JsonProperty("redirecturi")] - public string RedirectUri { get; set; } - - // TODO: this is a list, but lab sends a string. Not used today, discuss with lab to return a list - [JsonProperty("authority")] - public string Authority { get; set; } - - [JsonProperty("defaultscopes")] - public string DefaultScopes { get; set; } - } - - public class Lab - { - [JsonProperty("tenantid")] - public string TenantId { get; set; } - - [JsonProperty("federationprovider")] - public FederationProvider FederationProvider { get; set; } - - [JsonProperty("authority")] - public string Authority { get; set; } - } -} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabResponseHelper.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabResponseHelper.cs new file mode 100644 index 0000000000..23a944ab46 --- /dev/null +++ b/tests/Microsoft.Identity.Test.LabInfrastructure/LabResponseHelper.cs @@ -0,0 +1,220 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.Identity.Test.LabInfrastructure +{ + public static class LabResponseHelper + { + public static KeyVaultSecretsProvider KeyVaultSecretsProviderMsal { get; } + public static KeyVaultSecretsProvider KeyVaultSecretsProviderMsid { get; } + + // Caches for configuration objects retrieved from Key Vault + private static readonly System.Collections.Concurrent.ConcurrentDictionary s_userConfigCache = new(); + private static readonly System.Collections.Concurrent.ConcurrentDictionary s_appConfigCache = new(); + + static LabResponseHelper() + { + KeyVaultSecretsProviderMsal = new KeyVaultSecretsProvider(KeyVaultInstance.MsalTeam); + KeyVaultSecretsProviderMsid = new KeyVaultSecretsProvider(KeyVaultInstance.MSIDLab); + } + + /// + /// Retrieves user configuration from Key Vault with caching. + /// + /// The name of the Key Vault secret containing user configuration JSON. + /// A LabUser object deserialized from the Key Vault secret. + public static async Task GetUserConfigAsync(string secret) + { + // Check cache first + if (s_userConfigCache.TryGetValue(secret, out UserConfig cachedConfig)) + { + Debug.WriteLine($"UserConfig '{secret}' retrieved from cache"); + return cachedConfig; + } + + try + { + var keyVaultSecret = await KeyVaultSecretsProviderMsal.GetSecretByNameAsync(secret).ConfigureAwait(false); + string userData = keyVaultSecret.Value; + + if (string.IsNullOrEmpty(userData)) + { + Debug.WriteLine($"KeyVault secret '{secret}' empty"); + throw new InvalidOperationException($"Found no content for secret '{secret}' in Key Vault."); + } + + try + { + // Parse as JObject to extract the 'user' property (case-insensitive) + var jsonObject = JObject.Parse(userData); + var userToken = jsonObject.GetValue("user", StringComparison.OrdinalIgnoreCase); + + if (userToken == null) + { + Debug.WriteLine($"KeyVault '{secret}': no 'user' property found in JSON"); + throw new InvalidOperationException($"Key Vault secret '{secret}' does not contain a 'user' property."); + } + + var userConfig = userToken.ToObject() ?? throw new InvalidOperationException($"Failed to deserialize 'user' property from Key Vault secret '{secret}' to LabUser."); + Debug.WriteLine($"KeyVault '{secret}': {userConfig.Upn ?? "Unknown user"}"); + + // Cache the result + s_userConfigCache[secret] = userConfig; + return userConfig; + } + catch (JsonException jsonEx) + { + Debug.WriteLine($"KeyVault '{secret}': invalid JSON ({userData.Length} chars) - {jsonEx.Message}"); + throw new InvalidOperationException($"Key Vault secret '{secret}' contains invalid JSON for LabUser. {jsonEx.Message}", jsonEx); + } + } + catch (Exception e) when (!(e is InvalidOperationException)) + { + Debug.WriteLine($"KeyVault '{secret}' failed: {e.Message}"); + throw new InvalidOperationException($"Failed to retrieve or parse Key Vault secret '{secret}'. See inner exception.", e); + } + } + + /// + /// Retrieves app configuration from Key Vault with caching. + /// + /// The name of the Key Vault secret containing app configuration JSON. + /// An AppConfig object deserialized from the Key Vault secret. + public static async Task GetAppConfigAsync(string secret) + { + // Check cache first + if (s_appConfigCache.TryGetValue(secret, out AppConfig cachedConfig)) + { + Debug.WriteLine($"AppConfig '{secret}' retrieved from cache"); + return cachedConfig; + } + + try + { + var keyVaultSecret = await KeyVaultSecretsProviderMsal.GetSecretByNameAsync(secret).ConfigureAwait(false); + string appData = keyVaultSecret.Value; + + if (string.IsNullOrEmpty(appData)) + { + Debug.WriteLine($"KeyVault secret '{secret}' empty"); + throw new InvalidOperationException($"Found no content for secret '{secret}' in Key Vault."); + } + + try + { + // Parse as JObject to extract the 'app' property (case-insensitive) + var jsonObject = JObject.Parse(appData); + var appToken = jsonObject.GetValue("app", StringComparison.OrdinalIgnoreCase); + + if (appToken == null) + { + Debug.WriteLine($"KeyVault '{secret}': no 'app' property found in JSON"); + throw new InvalidOperationException($"Key Vault secret '{secret}' does not contain an 'app' property."); + } + + var appConfig = appToken.ToObject() ?? throw new InvalidOperationException($"Failed to deserialize 'app' property from Key Vault secret '{secret}' to AppConfig."); + Debug.WriteLine($"KeyVault '{secret}': {appConfig.AppId ?? "Unknown app"}"); + + // Cache the result + s_appConfigCache[secret] = appConfig; + return appConfig; + } + catch (JsonException jsonEx) + { + Debug.WriteLine($"KeyVault '{secret}': invalid JSON ({appData.Length} chars) - {jsonEx.Message}"); + throw new InvalidOperationException($"Key Vault secret '{secret}' contains invalid JSON for AppConfig. {jsonEx.Message}", jsonEx); + } + } + catch (Exception e) when (!(e is InvalidOperationException)) + { + Debug.WriteLine($"KeyVault '{secret}' failed: {e.Message}"); + throw new InvalidOperationException($"Failed to retrieve or parse Key Vault secret '{secret}'. See inner exception.", e); + } + } + + private static async Task> GetJsonOfKeyValuePairsFromKVAsync(string secret) + { + try + { + var keyVaultSecret = await KeyVaultSecretsProviderMsal.GetSecretByNameAsync(secret).ConfigureAwait(false); + string jsonData = keyVaultSecret.Value; + + if (string.IsNullOrEmpty(jsonData)) + { + Debug.WriteLine($"KeyVault secret '{secret}' empty"); + throw new InvalidOperationException($"Found no content for secret '{secret}' in Key Vault."); + } + + try + { + var keyValuePairs = JsonConvert.DeserializeObject>(jsonData); + if (keyValuePairs == null) + { + Debug.WriteLine($"KeyVault '{secret}': failed to deserialize to Dictionary"); + throw new InvalidOperationException($"Failed to deserialize Key Vault secret '{secret}' to Dictionary."); + } + + Debug.WriteLine($"KeyVault '{secret}': retrieved {keyValuePairs.Count} key-value pairs"); + return keyValuePairs; + } + catch (JsonException jsonEx) + { + Debug.WriteLine($"KeyVault '{secret}': invalid JSON ({jsonData.Length} chars) - {jsonEx.Message}"); + throw new InvalidOperationException($"Key Vault secret '{secret}' contains invalid JSON for Dictionary. {jsonEx.Message}", jsonEx); + } + } + catch (Exception e) when (!(e is InvalidOperationException)) + { + Debug.WriteLine($"KeyVault '{secret}' failed: {e.Message}"); + throw new InvalidOperationException($"Failed to retrieve or parse Key Vault secret '{secret}'. See inner exception.", e); + } + } + + public static Task> GetDefaultMSIEnvironmentVariablesAsync() + { + return GetJsonOfKeyValuePairsFromKVAsync("EnvVariables-MSI-Config"); + } + + public static string FetchUserPassword(string userLabName) + { + // TODO: Implement caching to avoid repeated Key Vault calls + if (string.IsNullOrWhiteSpace(userLabName)) + { + Debug.WriteLine("Password fetch failed: empty lab name"); + throw new InvalidOperationException("Error: lab name is not set on user. Password retrieval failed."); + } + + if (KeyVaultSecretsProviderMsid == null || KeyVaultSecretsProviderMsal == null) + { + Debug.WriteLine("Password fetch failed: KeyVault provider not initialized"); + throw new InvalidOperationException("Error: KeyVault secrets provider is not set"); + } + + try + { + var keyVaultSecret = KeyVaultSecretsProviderMsid.GetSecretByName(userLabName); + string password = keyVaultSecret.Value; + + if (!string.IsNullOrEmpty(password)) + { + Debug.WriteLine($"Password retrieved for {userLabName} ({password.Length} chars)"); + return password; + } + + Debug.WriteLine($"Password empty for {userLabName}"); + throw new InvalidOperationException($"Password secret '{userLabName}' found but was empty in Key Vault."); + } + catch (Exception e) + { + Debug.WriteLine($"Password fetch failed for {userLabName}: {e.Message}"); + throw new InvalidOperationException($"Test setup: cannot get the user password from Key Vault secret '{userLabName}'. See inner exception.", e); + } + } + } +} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceApi.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceApi.cs deleted file mode 100644 index 6bdd85355e..0000000000 --- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceApi.cs +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; -using Azure.Core; -using Newtonsoft.Json; - -namespace Microsoft.Identity.Test.LabInfrastructure -{ - /// - /// Wrapper for new lab service API - /// - public class LabServiceApi - { - private string _labAccessAppId; - private AccessToken? _labApiAccessToken; - private AccessToken? _msiHelperApiAccessToken; - - public LabServiceApi() - { - KeyVaultSecretsProvider _keyVaultSecretsProvider = new KeyVaultSecretsProvider(); - _labAccessAppId = _keyVaultSecretsProvider.GetSecretByName("LabVaultAppID").Value; - } - - /// - /// Returns a test user account for use in testing. - /// - /// Any and all parameters that the returned user should satisfy. - /// Users that match the given query parameters. - - public async Task GetLabResponseFromApiAsync(UserQuery query) - { - //Fetch user - string result = await RunQueryAsync(query).ConfigureAwait(false); - - if (string.IsNullOrWhiteSpace(result)) - { - throw new LabUserNotFoundException(query, "No lab user with specified parameters exists"); - } - - return CreateLabResponseFromResultStringAsync(result).Result; - } - - internal async Task CreateLabResponseFromResultStringAsync(string result) - { - LabUser[] userResponses = JsonConvert.DeserializeObject(result); - - var user = userResponses[0]; - - var appResponse = await GetLabResponseAsync(LabApiConstants.LabAppEndpoint + user.AppId).ConfigureAwait(false); - LabApp[] labApps = JsonConvert.DeserializeObject(appResponse); - - var labInfoResponse = await GetLabResponseAsync(LabApiConstants.LabInfoEndpoint + user.LabName).ConfigureAwait(false); - Lab[] labs = JsonConvert.DeserializeObject(labInfoResponse); - - user.TenantId = labs[0].TenantId; - user.FederationProvider = labs[0].FederationProvider; - - return new LabResponse - { - User = user, - App = labApps[0], - Lab = labs[0] - }; - } - - private Task RunQueryAsync(UserQuery query) - { - Dictionary queryDict = new Dictionary(); - if (string.IsNullOrEmpty(query.Upn)) - { - //Building user query - //Required parameters will be set to default if not supplied by the test code - - if (query.UserType != null) - { - queryDict.Add(LabApiConstants.UserType, query.UserType.ToString()); - } - - if (query.B2CIdentityProvider != null) - { - queryDict.Add(LabApiConstants.B2CProvider, query.B2CIdentityProvider.ToString()); - } - - if (query.FederationProvider != null) - { - queryDict.Add(LabApiConstants.FederationProvider, query.FederationProvider.ToString()); - } - - if (query.AzureEnvironment != null) - { - queryDict.Add(LabApiConstants.AzureEnvironment, query.AzureEnvironment.ToString()); - } - - if (query.SignInAudience != null) - { - queryDict.Add(LabApiConstants.SignInAudience, query.SignInAudience.ToString()); - } - - if (query.AppPlatform != null) - { - queryDict.Add(LabApiConstants.AppPlatform, query.AppPlatform.ToString()); - } - - if (query.PublicClient != null) - { - queryDict.Add(LabApiConstants.PublicClient, query.PublicClient.ToString()); - } - - return SendLabRequestAsync(LabApiConstants.LabEndPoint, queryDict); - } - else - { - return SendLabRequestAsync(LabApiConstants.LabEndPoint + "/" + query.Upn, queryDict); - } - } - - private async Task SendLabRequestAsync(string requestUrl, Dictionary queryDict) - { - UriBuilder uriBuilder = new UriBuilder(requestUrl); - - if (queryDict.Count > 0) - { -#pragma warning disable CA1305 // Specify IFormatProvider - uriBuilder.Query = string.Join("&", queryDict?.Select(x => x.Key + "=" + x.Value.ToString())); -#pragma warning restore CA1305 // Specify IFormatProvider - }; - - return await GetLabResponseAsync(uriBuilder.ToString()).ConfigureAwait(false); - } - - internal async Task GetLabResponseAsync(string address) - { - if (_labApiAccessToken == null) - _labApiAccessToken = await LabAuthenticationHelper.GetAccessTokenForLabAPIAsync(_labAccessAppId).ConfigureAwait(false); - - using (HttpClient httpClient = new HttpClient()) - { - httpClient.DefaultRequestHeaders.Add("Authorization", string.Format(CultureInfo.InvariantCulture, "bearer {0}", _labApiAccessToken.Value.Token)); - return await httpClient.GetStringAsync(address).ConfigureAwait(false); - } - } - - public async Task GetMSIHelperServiceTokenAsync() - { - if (_msiHelperApiAccessToken == null) - { - _msiHelperApiAccessToken = await LabAuthenticationHelper - .GetAccessTokenForLabAPIAsync(_labAccessAppId) - .ConfigureAwait(false); - } - - return _msiHelperApiAccessToken.Value.Token; - } - } -} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceParameters.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceParameters.cs deleted file mode 100644 index c98a563302..0000000000 --- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceParameters.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -namespace Microsoft.Identity.Test.LabInfrastructure -{ - public enum FederationProvider - { - Unknown, - None, - AdfsV4, - [Obsolete("ADFSv3 is out of support, do not use. The Arlingthon lab is federated to ADFSv3, so this value is needed")] - AdfsV3, - PingFederateV83, - Shibboleth, - ADFSv2019, - ADFSv2022, - B2C, - Ping, - CIAM, - CIAMCUD - } - - public enum B2CIdentityProvider - { - None, // Non-B2C user - Local, // Local B2C account - Facebook, - Google, - MSA, - Amazon, - Microsoft, - Twitter - } - - public enum UserType - { - Member, //V1 lab api only - Guest, - B2C, - Cloud, - Federated, - OnPrem, - MSA, - } - - public enum MFA - { - None, - MfaOnAll, - AutoMfaOnAll - } - - public enum ProtectionPolicy - { - None, - CA, - CADJ, - MAM, - MDM, - MDMCA, - MAMCA, - MAMSPO - } - - public enum HomeDomain //Must add ".com" to end for lab query - { - None, - MsidLab2, - MsidLab3, - MsidLab4 - } - - public enum HomeUPN //Must replace "_" with "@" add ".com" to end for lab query - { - None, - GidLab_Msidlab2, - GidLab_Msidlab3, - GidLab_Msidlab4, - } - - public enum AzureEnvironment - { - azurecloud, - azureb2ccloud, - azurechinacloud, - azuregermanycloud, - azureppe, - azureusgovernment - } - - public enum SignInAudience - { - AzureAdMyOrg, - AzureAdMultipleOrgs, - AzureAdAndPersonalMicrosoftAccount - } - - public enum AppPlatform - { - web, - spa - } - - public enum PublicClient - { - yes, - no - } -} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserHelper.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserHelper.cs deleted file mode 100644 index 69f54ae61c..0000000000 --- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserHelper.cs +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Microsoft.Identity.Test.LabInfrastructure -{ - public static class LabUserHelper - { - private static readonly LabServiceApi s_labService; - - public static KeyVaultSecretsProvider KeyVaultSecretsProviderMsal { get; } - public static KeyVaultSecretsProvider KeyVaultSecretsProviderMsid { get; } - - static LabUserHelper() - { - KeyVaultSecretsProviderMsal = new KeyVaultSecretsProvider(KeyVaultInstance.MsalTeam); - KeyVaultSecretsProviderMsid = new KeyVaultSecretsProvider(KeyVaultInstance.MSIDLab); - s_labService = new LabServiceApi(); - } - - - - private static async Task GetKVLabDataAsync(string secret) - { - // TODO: Implement caching to avoid repeated Key Vault calls - try - { - var keyVaultSecret = await KeyVaultSecretsProviderMsal.GetSecretByNameAsync(secret).ConfigureAwait(false); - string labData = keyVaultSecret.Value; - - if (string.IsNullOrEmpty(labData)) - { - Debug.WriteLine($"KeyVault secret '{secret}' empty"); - throw new LabUserNotFoundException(new UserQuery(), $"Found no content for secret '{secret}' in Key Vault."); - } - - try - { - // Parse JSON directly - let JsonException bubble up if invalid - var response = JsonConvert.DeserializeObject(labData) ?? throw new LabUserNotFoundException(new UserQuery(), $"Failed to deserialize Key Vault secret '{secret}' to LabResponse."); - Debug.WriteLine($"KeyVault '{secret}': {response.User?.Upn ?? response.App?.AppId ?? response.Lab?.TenantId ?? "Unknown"}"); - return response; - } - catch (JsonException jsonEx) - { - Debug.WriteLine($"KeyVault '{secret}': invalid JSON ({labData.Length} chars) - {jsonEx.Message}"); - throw new LabUserNotFoundException(new UserQuery(), $"Key Vault secret '{secret}' contains invalid JSON for LabResponse. {jsonEx.Message}"); - } - } - catch (Exception e) when (!(e is LabUserNotFoundException)) - { - Debug.WriteLine($"KeyVault '{secret}' failed: {e.Message}"); - throw new InvalidOperationException($"Failed to retrieve or parse Key Vault secret '{secret}'. See inner exception.", e); - } - } - - public static async Task MergeKVLabDataAsync(params string[] secrets) - { - if (secrets == null || secrets.Length == 0) - { - throw new ArgumentException("At least one secret name must be provided.", nameof(secrets)); - } - - try - { - LabResponse mergedResponse = null; - - foreach (string secret in secrets) - { - var labResponse = await GetKVLabDataAsync(secret).ConfigureAwait(false); - - if (mergedResponse == null) - { - mergedResponse = labResponse; - } - else - { - mergedResponse = MergeLabResponses(mergedResponse, labResponse); - } - } - - if (mergedResponse == null) - { - Debug.WriteLine($"Merge failed - no valid LabResponse in: {string.Join(", ", secrets)}"); - throw new LabUserNotFoundException(new UserQuery(), $"Failed to create merged LabResponse from secrets: {string.Join(", ", secrets)}"); - } - - Debug.WriteLine($"Merged [{string.Join(", ", secrets)}]: {mergedResponse.User?.Upn ?? "N/A"} | {mergedResponse.App?.AppId ?? "N/A"} | {mergedResponse.Lab?.TenantId ?? "N/A"}"); - return mergedResponse; - } - catch (Exception e) - { - Debug.WriteLine($"Merge failed [{string.Join(", ", secrets)}]: {e.Message}"); - throw new InvalidOperationException($"Failed to merge Key Vault secrets: {string.Join(", ", secrets)}. See inner exception.", e); - } - } - - private static LabResponse MergeLabResponses(LabResponse primary, LabResponse secondary) - { - var primaryJson = JObject.FromObject(primary); - var secondaryJson = JObject.FromObject(secondary); - - primaryJson.Merge(secondaryJson, new JsonMergeSettings - { - MergeArrayHandling = MergeArrayHandling.Union, - MergeNullValueHandling = MergeNullValueHandling.Ignore - }); - - return primaryJson.ToObject(); - } - - public static async Task GetMSIEnvironmentVariablesAsync(string uri) - { - string result = await s_labService.GetLabResponseAsync(uri).ConfigureAwait(false); - Debug.WriteLine($"MSI env vars: {result?.Length ?? 0} chars from {uri}"); - return result; - } - public static Task GetDefaultUserAsync() - { - return MergeKVLabDataAsync("MSAL-User-Default-JSON", "ID4SLAB1", "MSAL-App-Default-JSON"); - } - - public static Task GetDefaultUserWithMultiTenantAppAsync() - { - return MergeKVLabDataAsync("MSAL-User-Default-JSON", "ID4SLAB1", "MSAL-APP-AzureADMultipleOrgs-JSON"); - } - public static Task GetDefaultUser2Async() - { - return MergeKVLabDataAsync("MSAL-User-Default2-JSON", "ID4SLAB1", "MSAL-App-Default-JSON"); - } - public static Task GetDefaultUser3Async() - { - return MergeKVLabDataAsync("MSAL-User-XCG-JSON", "ID4SLAB1", "MSAL-App-Default-JSON"); - } - - public static Task GetDefaultAdfsUserAsync() - { - return MergeKVLabDataAsync("MSAL-USER-FedDefault-JSON", "ID4SLAB1", "MSAL-App-Default-JSON"); - } - - - - public static Task GetB2CLocalAccountAsync() - { - return MergeKVLabDataAsync("B2C-User-IDLab-JSON", "MSIDLABB2C", "B2C-App-IDLABSAPPB2C-JSON"); - } - - public static Task GetArlingtonUserAsync() - { - var response = MergeKVLabDataAsync("ARL-User-IDLab-JSON", "ARLMSIDLAB1", "ARL-App-IDLABSAPP-JSON"); - response.Result.User.AzureEnvironment = AzureEnvironment.azureusgovernment; - return response; - } - - public static Task GetArlingtonADFSUserAsync() - { - var response = MergeKVLabDataAsync("ARL-User-fIDLAB-JSON", "ARLMSIDLAB1", "ARL-App-IDLABSAPP-JSON"); - response.Result.User.AzureEnvironment = AzureEnvironment.azureusgovernment; - return response; - } - public static Task GetCIAMUserAsync() - { - return MergeKVLabDataAsync("MSAL-User-CIAM-JSON", "MSIDLABCIAM6", "MSAL-App-CIAM-JSON"); - } - - - - public static string FetchUserPassword(string userLabName) - { - // TODO: Implement caching to avoid repeated Key Vault calls - if (string.IsNullOrWhiteSpace(userLabName)) - { - Debug.WriteLine("Password fetch failed: empty lab name"); - throw new InvalidOperationException("Error: lab name is not set on user. Password retrieval failed."); - } - - if (KeyVaultSecretsProviderMsid == null || KeyVaultSecretsProviderMsal == null) - { - Debug.WriteLine("Password fetch failed: KeyVault provider not initialized"); - throw new InvalidOperationException("Error: KeyVault secrets provider is not set"); - } - - try - { - var keyVaultSecret = KeyVaultSecretsProviderMsid.GetSecretByName(userLabName); - string password = keyVaultSecret.Value; - - if (!string.IsNullOrEmpty(password)) - { - Debug.WriteLine($"Password retrieved for {userLabName} ({password.Length} chars)"); - return password; - } - - Debug.WriteLine($"Password empty for {userLabName}"); - throw new InvalidOperationException($"Password secret '{userLabName}' found but was empty in Key Vault."); - } - catch (Exception e) - { - Debug.WriteLine($"Password fetch failed for {userLabName}: {e.Message}"); - throw new InvalidOperationException($"Test setup: cannot get the user password from Key Vault secret '{userLabName}'. See inner exception.", e); - } - } - } -} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserNotFoundException.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserNotFoundException.cs deleted file mode 100644 index 07ecf2a875..0000000000 --- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserNotFoundException.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -namespace Microsoft.Identity.Test.LabInfrastructure -{ - public class LabUserNotFoundException : Exception - { - public UserQuery Parameters { get; set; } - - public LabUserNotFoundException(UserQuery parameters, string message):base(message) - { - Parameters = parameters; - } - } -} diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUser.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/UserConfig.cs similarity index 72% rename from tests/Microsoft.Identity.Test.LabInfrastructure/LabUser.cs rename to tests/Microsoft.Identity.Test.LabInfrastructure/UserConfig.cs index 3d0ffc3473..d7bba8ec41 100644 --- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUser.cs +++ b/tests/Microsoft.Identity.Test.LabInfrastructure/UserConfig.cs @@ -2,18 +2,17 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; using Newtonsoft.Json; namespace Microsoft.Identity.Test.LabInfrastructure { - public class LabUser + public class UserConfig { [JsonProperty("objectId")] public Guid ObjectId { get; set; } [JsonProperty("userType")] - public UserType UserType { get; set; } + public string UserType { get; set; } [JsonProperty("upn")] public string Upn { get; set; } @@ -22,12 +21,12 @@ public class LabUser public string HomeUPN { get; set; } [JsonProperty("b2cprovider")] - public B2CIdentityProvider B2cProvider { get; set; } + public string B2cProvider { get; set; } [JsonProperty("labname")] public string LabName { get; set; } - public FederationProvider FederationProvider { get; set; } + public string FederationProvider { get; set; } public string TenantId { get; set; } @@ -37,13 +36,13 @@ public class LabUser public string AppId { get; set; } [JsonProperty("azureenvironment")] - public AzureEnvironment AzureEnvironment { get; set; } + public string AzureEnvironment { get; set; } public string GetOrFetchPassword() { if (_password == null) { - _password = LabUserHelper.FetchUserPassword(LabName); + _password = LabResponseHelper.FetchUserPassword(LabName); } return _password; diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/UserQueryParameters.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/UserQueryParameters.cs deleted file mode 100644 index d1270bcbd1..0000000000 --- a/tests/Microsoft.Identity.Test.LabInfrastructure/UserQueryParameters.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; - -namespace Microsoft.Identity.Test.LabInfrastructure -{ - public struct UserQuery - { - public UserType? UserType { get; set; } - public B2CIdentityProvider? B2CIdentityProvider { get; set; } - public FederationProvider? FederationProvider { get; set; } //Requires userType to be set to federated - public AzureEnvironment? AzureEnvironment { get; set; } - public SignInAudience? SignInAudience { get; set; } - public AppPlatform? AppPlatform { get; set; } - public PublicClient? PublicClient { get; set; } - - /// - /// Ask for a specific user from the lab. No other parameters will be considered. - /// - public string Upn { get; set; } - - public static UserQuery PublicAadUserQuery => new UserQuery() - { - Upn = "MSAL-User-Default@id4slab1.onmicrosoft.com" - }; - - public static UserQuery PublicAadUser2Query => new UserQuery() - { - Upn = "MSAL-User-Default2@id4slab1.onmicrosoft.com" - }; - - public static UserQuery PublicAadUser3Query => new UserQuery() - { - Upn = "MSAL-User-XCG@id4slab1.onmicrosoft.com" - }; - - public static UserQuery MsaUserQuery => new UserQuery - { - UserType = LabInfrastructure.UserType.MSA - }; - - public static UserQuery B2CLocalAccountUserQuery => new UserQuery - { - UserType = LabInfrastructure.UserType.B2C, - B2CIdentityProvider = LabInfrastructure.B2CIdentityProvider.Local - }; - - public static UserQuery ArlingtonUserQuery => new UserQuery - { - UserType = LabInfrastructure.UserType.Cloud, - AzureEnvironment = LabInfrastructure.AzureEnvironment.azureusgovernment - }; - - public static UserQuery HybridSpaUserQuery => new UserQuery - { - UserType = LabInfrastructure.UserType.Cloud, - AppPlatform = LabInfrastructure.AppPlatform.spa, - PublicClient = LabInfrastructure.PublicClient.no, - SignInAudience = LabInfrastructure.SignInAudience.AzureAdMyOrg - - }; - } -} diff --git a/tests/devapps/DesktopTestApp/MainForm.cs b/tests/devapps/DesktopTestApp/MainForm.cs index 2e0ee60744..3615a16c9e 100644 --- a/tests/devapps/DesktopTestApp/MainForm.cs +++ b/tests/devapps/DesktopTestApp/MainForm.cs @@ -722,8 +722,8 @@ private async Task GetB2CClientIdFromLabAsync() { return; } - LabResponse labResponse = await LabUserHelper.GetB2CLocalAccountAsync().ConfigureAwait(false); - _b2CClientId = labResponse.App.AppId; + var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.B2CAppIdLabsAppB2C).ConfigureAwait(false); + _b2CClientId = app.AppId; } private void ciamCheckBox_CheckedChanged(object sender, EventArgs e) diff --git a/tests/devapps/NetCoreTestApp/Program.cs b/tests/devapps/NetCoreTestApp/Program.cs index 29e9117f9a..c7865b7bfb 100644 --- a/tests/devapps/NetCoreTestApp/Program.cs +++ b/tests/devapps/NetCoreTestApp/Program.cs @@ -30,7 +30,7 @@ public class Program }; // This app will be dynamically set to the multi-tenant app from lab - private static readonly string s_clientIdForPublicApp = LabUserHelper.GetDefaultUserWithMultiTenantAppAsync().Result.App.AppId; + private static readonly string s_clientIdForPublicApp = LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.MsalAppAzureAdMultipleOrgs).Result.AppId; private static readonly string s_username = ""; // used for WIA and U/P, cannot be empty on .net core