diff --git a/src/client/Microsoft.Identity.Lab.Api/LabInfra/KeyVaultSecrets.cs b/src/client/Microsoft.Identity.Lab.Api/LabInfra/KeyVaultSecrets.cs index 38b7d02170..ed9f82c191 100644 --- a/src/client/Microsoft.Identity.Lab.Api/LabInfra/KeyVaultSecrets.cs +++ b/src/client/Microsoft.Identity.Lab.Api/LabInfra/KeyVaultSecrets.cs @@ -83,6 +83,17 @@ public static class KeyVaultSecrets /// public const string MsalAppArlingtonCCA = "MSAL-App-ArlingtonCCA-JSON"; + /// + /// OBO service app (MSAL-APP-TodoListService) in ID4SLAB1 tenant. Used for On-Behalf-Of flow integration tests + /// with certificate-based authentication (LabAuth cert from msidlabs vault). + /// + public const string AppOBOService = "MSAL-APP-TodoListService-JSON"; + /// + /// OBO public client app (MSAL-APP-TodoListClient) in ID4SLAB1 tenant. Used as the public client + /// that acquires user tokens for On-Behalf-Of flow integration tests. + /// + public const string AppOBOClient = "MSAL-APP-TodoListClient-JSON"; + // Name of key vault secrets for app secrets and certificates /// /// default secret value used for testing application authentication scenarios that require a client secret. This secret is typically associated with a test application registered in Azure Active Directory and is used to validate authentication flows that involve client credentials or other secret-based authentication methods. diff --git a/src/client/Microsoft.Identity.Lab.Api/PublicAPI.Unshipped.txt b/src/client/Microsoft.Identity.Lab.Api/PublicAPI.Unshipped.txt index 5442e839b2..b888d02b2b 100644 --- a/src/client/Microsoft.Identity.Lab.Api/PublicAPI.Unshipped.txt +++ b/src/client/Microsoft.Identity.Lab.Api/PublicAPI.Unshipped.txt @@ -14,6 +14,8 @@ const Microsoft.Identity.Test.Common.TestCategories.UnifiedSchemaValidation = "U const Microsoft.Identity.Test.LabInfrastructure.KeyVaultInstance.MsalTeam = "https://id4skeyvault.vault.azure.net/" -> string const Microsoft.Identity.Test.LabInfrastructure.KeyVaultInstance.MSIDLab = "https://msidlabs.vault.azure.net" -> string const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppAdfsNativeClient = "App-AdfsNativeClient-Config" -> string +const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppOBOClient = "MSAL-APP-TodoListClient-JSON" -> string +const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppOBOService = "MSAL-APP-TodoListService-JSON" -> string const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppPCAClient = "App-PCAClient-Config" -> string const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppS2S = "App-S2S-Config" -> string const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppWebApi = "App-WebApi-Config" -> string diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/LongRunningOnBehalfOfTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/LongRunningOnBehalfOfTests.cs index bea98477e3..67809e191a 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/LongRunningOnBehalfOfTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/LongRunningOnBehalfOfTests.cs @@ -1,9 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System; using System.Linq; using System.Net; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using Microsoft.Identity.Client; @@ -22,18 +23,18 @@ public class LongRunningOnBehalfOfTests { private static readonly string[] s_scopes = { "User.Read" }; - private string _confidentialClientSecret; + private X509Certificate2 _labAuthCert; - private readonly KeyVaultSecretsProvider _keyVault = new KeyVaultSecretsProvider(KeyVaultInstance.MsalTeam); + private readonly KeyVaultSecretsProvider _keyVaultMsidLab = new KeyVaultSecretsProvider(KeyVaultInstance.MSIDLab); #region Test Hooks [TestInitialize] - public void TestInitialize() + public async Task TestInitializeAsync() { ApplicationBase.ResetStateForTest(); - if (string.IsNullOrEmpty(_confidentialClientSecret)) + if (_labAuthCert is null) { - _confidentialClientSecret = _keyVault.GetSecretByName(TestConstants.MsalOBOKeyVaultSecretName).Value; + _labAuthCert = await _keyVaultMsidLab.GetCertificateWithPrivateMaterialAsync("LabAuth").ConfigureAwait(false); } } @@ -51,7 +52,7 @@ public async Task LongRunningAndNormalObo_WithDifferentKeys_TestAsync() { var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); var pca = PublicClientApplicationBuilder .Create(app.AppId) @@ -106,7 +107,7 @@ public async Task LongRunningThenNormalObo_WithTheSameKey_TestAsync() { var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); var pca = PublicClientApplicationBuilder .Create(app.AppId) @@ -182,7 +183,7 @@ public async Task InitiateLRWithCustomKey_ThenAcquireLRWithSameKey_Succeeds_Test // Arrange var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); IPublicClientApplication pca = PublicClientApplicationBuilder .Create(app.AppId) @@ -256,7 +257,7 @@ public async Task NormalOboThenLongRunningAcquire_WithTheSameKey_TestAsync() { var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); var pca = PublicClientApplicationBuilder .Create(app.AppId) @@ -330,7 +331,7 @@ public async Task NormalOboThenLongRunningInitiate_WithTheSameKey_TestAsync() { var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); var pca = PublicClientApplicationBuilder .Create(app.AppId) @@ -389,7 +390,7 @@ public async Task WithDifferentScopes_TestAsync() { var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); var pca = PublicClientApplicationBuilder .Create(app.AppId) @@ -442,7 +443,7 @@ private ConfidentialClientApplication BuildCCA(string tenantId, string appId) var builder = ConfidentialClientApplicationBuilder .Create(appId) .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"), true) - .WithClientSecret(_confidentialClientSecret) + .WithCertificate(_labAuthCert) .WithLegacyCacheCompatibility(false); return builder.BuildConcrete(); diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/OnBehalfOfTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/OnBehalfOfTests.cs index f74618e46c..568f26a791 100644 --- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/OnBehalfOfTests.cs +++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/OnBehalfOfTests.cs @@ -1,10 +1,11 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System; using System.Collections.Generic; using System.Linq; using System.Net; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using Microsoft.Identity.Client; @@ -24,24 +25,21 @@ namespace Microsoft.Identity.Test.Integration.HeadlessTests public class OnBehalfOfTests { private static readonly string[] s_scopes = { "User.Read" }; - //private static readonly string[] s_oboServiceScope = { "api://23c64cd8-21e4-41dd-9756-ab9e2c23f58c/access_as_user" }; - //const string OboConfidentialClientID = "23c64cd8-21e4-41dd-9756-ab9e2c23f58c"; private static InMemoryTokenCache s_inMemoryTokenCache = new InMemoryTokenCache(); - private string _confidentialClientSecret; + private X509Certificate2 _labAuthCert; - private readonly KeyVaultSecretsProvider _keyVault = new KeyVaultSecretsProvider(KeyVaultInstance.MsalTeam); private readonly KeyVaultSecretsProvider _keyVaultMsidLab = new KeyVaultSecretsProvider(KeyVaultInstance.MSIDLab); #region Test Hooks [TestInitialize] - public void TestInitialize() + public async Task TestInitializeAsync() { ApplicationBase.ResetStateForTest(); - if (string.IsNullOrEmpty(_confidentialClientSecret)) + if (_labAuthCert is null) { - _confidentialClientSecret = _keyVault.GetSecretByName(TestConstants.MsalOBOKeyVaultSecretName).Value; + _labAuthCert = await _keyVaultMsidLab.GetCertificateWithPrivateMaterialAsync("LabAuth").ConfigureAwait(false); } } @@ -61,7 +59,7 @@ public async Task OboAndSilent_ReturnsCorrectTokens_TestAsync(bool serializeCach var user1 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); var user2 = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud2).ConfigureAwait(false); var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); var partitionedInMemoryTokenCache = new InMemoryPartitionedTokenCache(); var nonPartitionedInMemoryTokenCache = new InMemoryTokenCache(); @@ -152,7 +150,7 @@ IConfidentialClientApplication CreateCCA() var app = ConfidentialClientApplicationBuilder .Create(appApi.AppId) .WithAuthority(new Uri($"https://login.microsoftonline.com/{user1AuthResult.TenantId}"), true) - .WithClientSecret(_confidentialClientSecret) + .WithCertificate(_labAuthCert) .WithLegacyCacheCompatibility(false) .Build(); @@ -182,7 +180,7 @@ public async Task OboAndClientCredentials_WithRegional_ReturnsCorrectTokens_Test // Setup: Get lab user, create PCA and get user tokens var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); // Use the correct public client ID from KeyVault for all tests var publicClientId = app.AppId; @@ -305,7 +303,7 @@ public async Task WithCache_TestAsync() { var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserPublicCloud).ConfigureAwait(false); var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); var factory = new HttpSnifferClientFactory(); @@ -325,7 +323,7 @@ public async Task WithCache_TestAsync() var confidentialApp = ConfidentialClientApplicationBuilder .Create(appApi.AppId) .WithAuthority(new Uri("https://login.microsoftonline.com/" + authResult.TenantId), true) - .WithClientSecret(_confidentialClientSecret) + .WithCertificate(_labAuthCert) .WithTestLogging() .BuildConcrete(); @@ -378,7 +376,7 @@ public async Task WithCache_TestAsync() var confidentialApp2 = ConfidentialClientApplicationBuilder .Create(appApi.AppId) .WithAuthority(new Uri("https://login.microsoftonline.com/" + authResult.TenantId), true) - .WithClientSecret(_confidentialClientSecret) + .WithCertificate(_labAuthCert) .WithTestLogging() .WithHttpClientFactory(factory) .BuildConcrete(); @@ -438,7 +436,7 @@ private async Task RunOnBehalfOfTestAsync( multiTenantAppId = app.AppId; } - var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); + var appApi = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); var pca = PublicClientApplicationBuilder .Create(multiTenantAppId) @@ -475,7 +473,7 @@ private async Task RunOnBehalfOfTestAsync( .Create(appApi.AppId) .WithAuthority(new Uri("https://login.microsoftonline.com/" + authResult.TenantId), true) .WithTestLogging(out HttpSnifferClientFactory factory) - .WithClientSecret(_confidentialClientSecret) + .WithCertificate(_labAuthCert) .Build(); s_inMemoryTokenCache.Bind(cca.UserTokenCache); @@ -522,20 +520,17 @@ void AssertExtraHttpHeadersAreSent(HttpSnifferClientFactory factory) private async Task BuildCcaAsync(string tenantId, bool withRegion = false) { - var appConfig = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S).ConfigureAwait(false); - var appApiConfig = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppWebApi).ConfigureAwait(false); - string secret = LabResponseHelper.FetchSecretString(appConfig.SecretName, LabResponseHelper.KeyVaultSecretsProviderMsal); + var appApiConfig = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppOBOService).ConfigureAwait(false); var builder = ConfidentialClientApplicationBuilder - .Create(withRegion ? appApiConfig.AppId : appConfig.AppId) + .Create(appApiConfig.AppId) .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"), true) - .WithClientSecret(withRegion ? _confidentialClientSecret : secret) + .WithCertificate(_labAuthCert, true) .WithLegacyCacheCompatibility(false); if (withRegion) { - builder - .WithAzureRegion(TestConstants.Region); + builder.WithAzureRegion(TestConstants.Region); } return builder.BuildConcrete();