diff --git a/Directory.Packages.props b/Directory.Packages.props
index d523737aa9..a75cac1ef8 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,7 +4,7 @@
0.16.2
- 4.61.0
+ 4.99.0-internal
@@ -40,8 +40,10 @@
-
-
+
+
+
+
diff --git a/src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs b/src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs
index e954ed2d12..bf39010a27 100644
--- a/src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs
+++ b/src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs
@@ -211,7 +211,7 @@ private async Task TryGetTokenUsingFociAsync(CancellationToke
{
// Hack: STS does not yet send back the suberror on these platforms because they are not in an allowed list,
// so the best thing we can do is to consider all errors as client_mismatch.
-#if NETSTANDARD || MAC
+#if NETSTANDARD
ex?.GetType(); // avoid the "variable 'ex' is declared but never used" in this code path.
return null;
#else
diff --git a/tests/CacheCompat/CommonCache.Test.Unit/CacheExecutionTests.cs b/tests/CacheCompat/CommonCache.Test.Unit/CacheExecutionTests.cs
index dcb4ad8e6e..172c64629b 100644
--- a/tests/CacheCompat/CommonCache.Test.Unit/CacheExecutionTests.cs
+++ b/tests/CacheCompat/CommonCache.Test.Unit/CacheExecutionTests.cs
@@ -19,8 +19,8 @@ public class CacheExecutionTests
private static async Task GetPublicAadUserDataAsync()
{
- var api = new LabServiceApi();
- LabResponse labResponse = (await api.GetLabResponseFromApiAsync(UserQuery.PublicAadUserQuery).ConfigureAwait(false));
+ LabResponse labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false);
+
return new LabUserData(
labResponse.User.Upn,
labResponse.User.GetOrFetchPassword(),
diff --git a/tests/Microsoft.Identity.Test.Common/Core/Helpers/CertHelper.cs b/tests/Microsoft.Identity.Test.Common/Core/Helpers/CertHelper.cs
new file mode 100644
index 0000000000..568746734a
--- /dev/null
+++ b/tests/Microsoft.Identity.Test.Common/Core/Helpers/CertHelper.cs
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Microsoft.Identity.Test.Common.Core.Helpers
+{
+ public static class CertificateFinder
+ {
+ ///
+ /// Try and locate a certificate matching the given by searching in
+ /// the store subjectName for all available s.
+ ///
+ /// Thumbprint of certificate to locate
+ /// with , or null if no matching certificate was found
+ public static X509Certificate2 FindCertificateByName(string subjectName)
+ {
+ foreach (StoreLocation storeLocation in Enum.GetValues(typeof(StoreLocation)))
+ {
+ var certificate = FindCertificateByName(subjectName, storeLocation, StoreName.My);
+ if (certificate != null)
+ {
+ return certificate;
+ }
+ }
+
+ return null;
+ }
+ ///
+ /// Try and locate a certificate matching the given by searching in
+ /// the in the given and .
+ ///
+ /// Thumbprint of certificate to locate
+ /// in which to search for a matching certificate
+ /// in which to search for a matching certificate
+ /// with , or null if no matching certificate was found
+ public static X509Certificate2 FindCertificateByName(string certName, StoreLocation location, StoreName name)
+ {
+ // Don't validate certs, since the test root isn't installed.
+ const bool validateCerts = false;
+
+ using (var store = new X509Store(name, location))
+ {
+ store.Open(OpenFlags.ReadOnly);
+ X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectName, certName, validateCerts);
+
+ X509Certificate2 certToUse = null;
+
+ // select the "freshest" certificate
+ foreach (X509Certificate2 cert in collection)
+ {
+ if (certToUse == null || cert.NotBefore > certToUse.NotBefore)
+ {
+ certToUse = cert;
+ }
+ }
+
+ return certToUse;
+
+ }
+ }
+ }
+
+ public enum KnownTestCertType
+ {
+ RSA,
+ ECD
+ }
+}
diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/CiamIntegrationTests.cs b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/CiamIntegrationTests.cs
index 02076ed760..6affcf562b 100644
--- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/CiamIntegrationTests.cs
+++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/CiamIntegrationTests.cs
@@ -32,11 +32,7 @@ public async Task ROPC_Ciam_StandardDomains_CompletesSuccessfully()
{
string authority;
//Get lab details
- var labResponse = await LabUserHelper.GetLabUserDataAsync(new UserQuery()
- {
- FederationProvider = FederationProvider.CIAMCUD,
- SignInAudience = SignInAudience.AzureAdMyOrg
- }).ConfigureAwait(false);
+ var labResponse = await LabUserHelper.GetCiamUserAync().ConfigureAwait(false);
//https://tenantName.ciamlogin.com/
authority = string.Format("https://{0}.ciamlogin.com/", labResponse.User.LabName);
@@ -87,12 +83,7 @@ public async Task ClientCredentialCiam_WithClientCredentials_ReturnsValidTokens(
{
string authority;
//Get lab details
- var labResponse = await LabUserHelper.GetLabUserDataAsync(new UserQuery()
- {
- FederationProvider = FederationProvider.CIAMCUD,
- SignInAudience = SignInAudience.AzureAdMyOrg
- }).ConfigureAwait(false);
-
+ var labResponse = await LabUserHelper.GetCiamUserAync().ConfigureAwait(false);
//https://tenantName.ciamlogin.com/
authority = string.Format("https://{0}.ciamlogin.com/", labResponse.User.LabName);
@@ -117,7 +108,7 @@ private async Task RunCiamCCATest(string authority, string appId)
//Acquire tokens
var msalConfidentialClientBuilder = ConfidentialClientApplicationBuilder
.Create(appId)
- .WithCertificate(CertificateHelper.FindCertificateByName(TestConstants.AutomationTestCertName))
+ .WithCertificate(CertificateFinder.FindCertificateByName(TestConstants.AutomationTestCertName))
.WithExperimentalFeatures();
if (authority.Contains(Constants.CiamAuthorityHostSuffix))
@@ -157,11 +148,7 @@ public async Task OBOCiam_CustomDomain_ReturnsValidTokens()
string ciamWebApi = "634de702-3173-4a71-b336-a4fab786a479";
//Get lab details
- LabResponse labResponse = await LabUserHelper.GetLabUserDataAsync(new UserQuery()
- {
- FederationProvider = FederationProvider.CIAMCUD,
- SignInAudience = SignInAudience.AzureAdMyOrg
- }).ConfigureAwait(false);
+ var labResponse = await LabUserHelper.GetCiamUserAync().ConfigureAwait(false);
//Acquire tokens
var msalPublicClient = PublicClientApplicationBuilder
@@ -184,7 +171,7 @@ public async Task OBOCiam_CustomDomain_ReturnsValidTokens()
//Acquire tokens for OBO
var msalConfidentialClient = ConfidentialClientApplicationBuilder
.Create(ciamWebApi)
- .WithCertificate(CertificateHelper.FindCertificateByName(TestConstants.AutomationTestCertName))
+ .WithCertificate(CertificateFinder.FindCertificateByName(TestConstants.AutomationTestCertName))
.WithAuthority(authorityCud, false)
.WithRedirectUri(_ciamRedirectUri)
.BuildConcrete();
@@ -212,11 +199,5 @@ public async Task OBOCiam_CustomDomain_ReturnsValidTokens()
Assert.AreEqual(atHash, userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheKey);
Assert.AreEqual(TokenSource.Cache, resultObo.AuthenticationResultMetadata.TokenSource);
}
-
- private string GetCiamSecret()
- {
- KeyVaultSecretsProvider provider = new KeyVaultSecretsProvider();
- return provider.GetSecretByName("msidlabciam2-cc").Value;
- }
}
}
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 27e443c9b3..839873bc5c 100644
--- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ClientCredentialsTests.NetFwk.cs
+++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ClientCredentialsTests.NetFwk.cs
@@ -64,11 +64,11 @@ public async Task RefreshOnIsEnabled(bool useRegional)
Assert.Inconclusive("Can't run regional on local devbox.");
}
- var cert = CertificateHelper.FindCertificateByName(TestConstants.AutomationTestCertName);
+ var cert = CertificateFinder.FindCertificateByName(TestConstants.AutomationTestCertName);
- var builder = ConfidentialClientApplicationBuilder.Create(LabAuthenticationHelper.LabAccessConfidentialClientId)
+ var builder = ConfidentialClientApplicationBuilder.Create(LabApiConstants.LabClientId)
.WithCertificate(cert, sendX5C: true)
- .WithAuthority(LabAuthenticationHelper.LabClientInstance, LabAuthenticationHelper.LabClientTenantId);
+ .WithAuthority(LabApiConstants.LabClientInstance, LabApiConstants.LabClientTenantId);
// auto-detect should work on Azure DevOps build
if (useRegional)
@@ -76,7 +76,7 @@ public async Task RefreshOnIsEnabled(bool useRegional)
var cca = builder.Build();
- var result = await cca.AcquireTokenForClient([LabAuthenticationHelper.LabScope]).ExecuteAsync().ConfigureAwait(false);
+ var result = await cca.AcquireTokenForClient([LabApiConstants.LabScope]).ExecuteAsync().ConfigureAwait(false);
Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource);
Assert.IsTrue(result.AuthenticationResultMetadata.RefreshOn.HasValue, "refresh_in was not issued - did the MSAL SKU value change?");
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 b60c70f865..6bf263d701 100644
--- a/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/PoPTests.NetFwk.cs
+++ b/tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/PoPTests.NetFwk.cs
@@ -770,7 +770,7 @@ public void CheckPopRuntimeBrokerSupportTest()
private static X509Certificate2 GetCertificate()
{
- X509Certificate2 cert = CertificateHelper.FindCertificateByName(TestConstants.AutomationTestCertName);
+ X509Certificate2 cert = CertificateFinder.FindCertificateByName(TestConstants.AutomationTestCertName);
if (cert == null)
{
diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/ConfidentialAppSettings.cs b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/ConfidentialAppSettings.cs
index db63ff07bd..f9054561f1 100644
--- a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/ConfidentialAppSettings.cs
+++ b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/ConfidentialAppSettings.cs
@@ -3,6 +3,7 @@
using System;
using System.Security.Cryptography.X509Certificates;
+using Microsoft.Identity.Test.Common.Core.Helpers;
using Microsoft.Identity.Test.LabInfrastructure;
using Microsoft.Identity.Test.Unit;
@@ -196,7 +197,7 @@ public static IConfidentialAppSettings GetSettings(Cloud cloud)
public static Lazy GetCertificateLazy(string certName) => new Lazy(() =>
{
- X509Certificate2 cert = CertificateHelper.FindCertificateByName(certName);
+ X509Certificate2 cert = CertificateFinder.FindCertificateByName(certName);
if (cert == null)
{
throw new InvalidOperationException(
diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsiProxyHttpManager.cs b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsiProxyHttpManager.cs
index aada0b10d4..8ca37e143a 100644
--- a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsiProxyHttpManager.cs
+++ b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/MsiProxyHttpManager.cs
@@ -3,16 +3,12 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography.X509Certificates;
-using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using System.Web;
-using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Core;
using Microsoft.Identity.Client.Http;
using Microsoft.Identity.Test.LabInfrastructure;
diff --git a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/PoPValidator.cs b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/PoPValidator.cs
index e92822ddc7..8cdfa5927c 100644
--- a/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/PoPValidator.cs
+++ b/tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/PoPValidator.cs
@@ -17,12 +17,7 @@ namespace Microsoft.Identity.Test.Integration.Infrastructure
public class PoPValidator
{
// This endpoint is hosted in the MSID Lab and is able to verify any pop token bound to an HTTP request
- 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(
- "automation-pop-validation-endpoint",
- "841fc7c2ccdd48d7a9ef727e4ae84325").Value);
///
/// This calls a special endpoint that validates any POP token against a configurable HTTP request.
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/CertificateHelper.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/CertificateHelper.cs
index 1c4519e621..c06788d1ec 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/CertificateHelper.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/CertificateHelper.cs
@@ -6,7 +6,7 @@
namespace Microsoft.Identity.Test.LabInfrastructure
{
- public static class CertificateHelper
+ internal static class CertificateHelper
{
///
/// Try and locate a certificate matching the given by searching in
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultConfiguration.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultConfiguration.cs
deleted file mode 100644
index 4a274cfe93..0000000000
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultConfiguration.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-namespace Microsoft.Identity.Test.LabInfrastructure
-{
- public class KeyVaultConfiguration
- {
- ///
- /// The URL of the Key Vault instance.
- ///
- public string Url { get; set; }
-
- ///
- /// The authentication type to use to communicate with the Key Vault.
- ///
- public LabAccessAuthenticationType AuthType { get; set; }
-
- ///
- /// The ID of the test harness client.
- ///
- ///
- /// This should be configured as having access to the Key Vault instance specified at .
- ///
- public string ClientId { get; set; }
-
- ///
- /// The thumbprint of the to use when
- /// is .
- ///
- public string CertThumbprint { get; set; }
-
- ///
- /// Secret value used to access Key Vault
- ///
- public string KeyVaultSecret { get; set; }
- }
-
-}
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecretsProvider.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecretsProvider.cs
index a15ce42636..8d3993db44 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecretsProvider.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/KeyVaultSecretsProvider.cs
@@ -24,7 +24,7 @@ public class KeyVaultInstance
public const string MsalTeam = "https://buildautomation.vault.azure.net/";
}
- public class KeyVaultSecretsProvider : IDisposable
+ public class KeyVaultSecretsProvider
{
private CertificateClient _certificateClient;
private SecretClient _secretClient;
@@ -58,43 +58,20 @@ public class KeyVaultSecretsProvider : IDisposable
///
public KeyVaultSecretsProvider(string keyVaultAddress = KeyVaultInstance.MSIDLab)
{
- var credentials = GetKeyVaultCredentialAsync().GetAwaiter().GetResult();
+ var credential = LabAuthenticationHelper.GetTokenCredential();
var keyVaultAddressUri = new Uri(keyVaultAddress);
- _certificateClient = new CertificateClient(keyVaultAddressUri, credentials);
- _secretClient = new SecretClient(keyVaultAddressUri, credentials);
- }
-
- ~KeyVaultSecretsProvider()
- {
- Dispose();
+ _certificateClient = new CertificateClient(keyVaultAddressUri, credential);
+ _secretClient = new SecretClient(keyVaultAddressUri, credential);
}
public KeyVaultSecret GetSecretByName(string secretName)
{
return _secretClient.GetSecret(secretName).Value;
}
-
- public KeyVaultSecret GetSecretByName(string secretName, string secretVersion)
- {
- return _secretClient.GetSecret(secretName, secretVersion).Value;
- }
-
+
public async Task GetCertificateWithPrivateMaterialAsync(string certName)
{
return await _certificateClient.DownloadCertificateAsync(certName).ConfigureAwait(false);
- }
-
- private async Task GetKeyVaultCredentialAsync()
- {
- var accessToken = await LabAuthenticationHelper.GetLabAccessTokenAsync(
- "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/",
- new[] { "https://vault.azure.net/.default" }).ConfigureAwait(false);
- return DelegatedTokenCredential.Create((_, __) => accessToken);
- }
-
- public void Dispose()
- {
- GC.SuppressFinalize(this);
- }
+ }
}
}
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabApiConstants.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabApiConstants.cs
index 14338c9e2e..690a468887 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabApiConstants.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/LabApiConstants.cs
@@ -3,7 +3,24 @@
namespace Microsoft.Identity.Test.LabInfrastructure
{
- public class LabApiConstants
+ public static class LabApiConstants
+ {
+ //public const string LabClientId = "f62c5ae3-bf3a-4af5-afa8-a68b800396e9";
+ //public const string LabScope = "https://request.msidlab.com/.default";
+
+ // IdentityLabsOneAccess
+ //public const string LabClientId = "00bedee1-0e09-4a8d-81a0-0679c5a64a83";
+ //public const string LabScope = "https://request.msidlab.com/.default";
+
+
+ public const string LabClientId = "5741af7e-6c00-4ed9-b589-73366d58a430";
+ public const string LabScope = "https://request.msidlab.com/.default";
+
+ public const string LabClientInstance = "https://login.microsoftonline.com/";
+ public const string LabClientTenantId = "72f988bf-86f1-41af-91ab-2d7cd011db47";
+ }
+
+ internal static class InternalConstants
{
// constants for Lab api
public const string MobileDeviceManagementWithConditionalAccess = "mdmca";
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabAuthenticationHelper.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabAuthenticationHelper.cs
index abc5671352..3bd9eea8c5 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabAuthenticationHelper.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/LabAuthenticationHelper.cs
@@ -2,78 +2,99 @@
// Licensed under the MIT License.
using System;
-using System.IO;
-using System.Security.Cryptography.X509Certificates;
-using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
-using Microsoft.Identity.Client;
-using Microsoft.Identity.Test.Unit;
-using Microsoft.Identity.Test.Common.Core.Mocks;
+using Azure.Identity;
+using System.Runtime.InteropServices;
+using Azure.Identity.Broker;
+using System.Diagnostics;
namespace Microsoft.Identity.Test.LabInfrastructure
{
- public static class LabAuthenticationHelper
+ internal static class LabAuthenticationHelper
{
- public const string LabAccessConfidentialClientId = "f62c5ae3-bf3a-4af5-afa8-a68b800396e9";
- public const string LabScope = "https://request.msidlab.com/.default";
- public const string LabClientInstance = "https://login.microsoftonline.com/";
- public const string LabClientTenantId = "72f988bf-86f1-41af-91ab-2d7cd011db47";
+ public static async Task GetAccessTokenForLabAPIAsync()
+ {
+ var tokenCredential = GetTokenCredential();
+
+ return await tokenCredential
+ .GetTokenAsync(new TokenRequestContext([LabApiConstants.LabScope]), default)
+ .ConfigureAwait(false);
+ }
- public static async Task GetAccessTokenForLabAPIAsync(string labAccessClientId)
+ public static async Task GetKeyVaultAccessToken()
{
- string[] scopes = new string[] { LabScope };
+ var tokenCredential = GetTokenCredential();
- return await GetLabAccessTokenAsync(
- LabClientInstance + LabClientTenantId,
- scopes,
- labAccessClientId).ConfigureAwait(false);
+ return await tokenCredential
+ .GetTokenAsync(new TokenRequestContext(["https://vault.azure.net/.default"]), default)
+ .ConfigureAwait(false);
}
- public static async Task GetLabAccessTokenAsync(string authority, string[] scopes)
+ internal static TokenCredential GetTokenCredential()
{
- return await GetLabAccessTokenAsync(
- authority,
- scopes,
- String.Empty).ConfigureAwait(false);
+ TokenCredential tokenCredential;
+ if (Environment.GetEnvironmentVariable("TF_BUILD") == null)
+ {
+ Debug.WriteLine("[LabAPI] Not on CI, using interactive browser/broker credential");
+ tokenCredential = GetAzureCredentialForDevBox();
+ }
+ else
+ {
+ Debug.WriteLine("[LabAPI] On CI, using ADO federation");
+ tokenCredential = GetAzureCredentialForCI();
+ }
+
+ return tokenCredential;
}
- public static async Task GetLabAccessTokenAsync(string authority, string[] scopes, string clientId)
+ private static TokenCredential GetAzureCredentialForCI()
{
- AuthenticationResult authResult;
- IConfidentialClientApplication confidentialApp;
- X509Certificate2 cert;
+ // as per https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/samples/OtherCredentialSamples.md#authenticating-in-azure-pipelines-with-service-connections
- var clientIdForCertAuth = String.IsNullOrEmpty(clientId) ? LabAccessConfidentialClientId : clientId;
+ string clientId = "4b7a4b0b-ecb2-409e-879a-1e21a15ddaf6"; // UAMI client ID
+ string tenantId = LabApiConstants.LabClientTenantId;
+ string serviceConnectionId = "6eeeb73d-37aa-4d78-83b7-728101b8bddd";
- cert = CertificateHelper.FindCertificateByName(TestConstants.AutomationTestCertName);
- if (cert == null)
- {
- throw new InvalidOperationException(
- "Test setup error - cannot find a certificate in the My store for KeyVault. This is available for Microsoft employees only.");
- }
+ var pipelinesCredential = new AzurePipelinesCredential(
+ tenantId,
+ clientId,
+ serviceConnectionId,
+ Environment.GetEnvironmentVariable("SYSTEM_ACCESSTOKEN"),
+ new AzurePipelinesCredentialOptions()
+ {
+ TokenCachePersistenceOptions = new TokenCachePersistenceOptions()
+ {
+ Name = "MSIDLabTokenCache",
+ UnsafeAllowUnencryptedStorage = true // We generally use headless Linux, so cannot use LibSecret. This is the ~same level of protection as SSH keys.
+ }
+ });
+
+ return pipelinesCredential;
+ }
- confidentialApp = ConfidentialClientApplicationBuilder
- .Create(clientIdForCertAuth)
- .WithAuthority(new Uri(authority), true)
- .WithCacheOptions(CacheOptions.EnableSharedCacheOptions)
- .WithCertificate(cert, true)
- .Build();
+ // TODO: test this on MacOs / Linux WSL
+ private static TokenCredential GetAzureCredentialForDevBox()
+ {
+ InteractiveBrowserCredential interactiveBrowserCredential = new InteractiveBrowserCredential(
+ new InteractiveBrowserCredentialBrokerOptions(GetForegroundWindow())
+ {
+ ClientId = LabApiConstants.LabClientId,
+ TenantId = LabApiConstants.LabClientTenantId,
+ TokenCachePersistenceOptions = new TokenCachePersistenceOptions()
+ {
+ Name = "MSIDLabTokenCache",
+ UnsafeAllowUnencryptedStorage = true // We generally use headless Linux, so cannot use LibSecret. This is the ~same level of protection as SSH keys.
+ },
+ RedirectUri = new Uri("http://localhost"), // On Mac and Linux, MSAL will fallback to browser
+ UseDefaultBrokerAccount = true //
- authResult = await confidentialApp
- .AcquireTokenForClient(scopes)
- .WithSendX5C(true)
- .ExecuteAsync(CancellationToken.None)
- .ConfigureAwait(false);
+ });
- return new AccessToken(authResult.AccessToken, authResult.ExpiresOn);
+ return interactiveBrowserCredential;
}
- }
- public enum LabAccessAuthenticationType
- {
- ClientCertificate,
- ClientSecret,
- UserCredential
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetForegroundWindow();
}
}
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceApi.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceApi.cs
index 840412c50d..241a17803b 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceApi.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceApi.cs
@@ -15,16 +15,25 @@ namespace Microsoft.Identity.Test.LabInfrastructure
///
/// Wrapper for new lab service API
///
- public class LabServiceApi
+ public class LabServiceApi
{
- private string _labAccessAppId;
private AccessToken? _labApiAccessToken;
private AccessToken? _msiHelperApiAccessToken;
public LabServiceApi()
{
- KeyVaultSecretsProvider _keyVaultSecretsProvider = new KeyVaultSecretsProvider();
- _labAccessAppId = _keyVaultSecretsProvider.GetSecretByName("LabVaultAppID").Value;
+ }
+
+ public async Task GetMSIHelperServiceTokenAsync()
+ {
+ if (_msiHelperApiAccessToken == null)
+ {
+ _msiHelperApiAccessToken = await LabAuthenticationHelper
+ .GetAccessTokenForLabAPIAsync()
+ .ConfigureAwait(false);
+ }
+
+ return _msiHelperApiAccessToken.Value.Token;
}
///
@@ -33,14 +42,15 @@ public LabServiceApi()
/// Any and all parameters that the returned user should satisfy.
/// Users that match the given query parameters.
- public async Task GetLabResponseFromApiAsync(UserQuery query)
+ internal 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");
+ throw new LabUserNotFoundException(
+ "No lab user with specified parameters exists: " + query.ToString());
}
return CreateLabResponseFromResultStringAsync(result).Result;
@@ -52,10 +62,10 @@ internal async Task CreateLabResponseFromResultStringAsync(string r
var user = userResponses[0];
- var appResponse = await GetLabResponseAsync(LabApiConstants.LabAppEndpoint + user.AppId).ConfigureAwait(false);
+ var appResponse = await GetLabResponseAsync(InternalConstants.LabAppEndpoint + user.AppId).ConfigureAwait(false);
LabApp[] labApps = JsonConvert.DeserializeObject(appResponse);
- var labInfoResponse = await GetLabResponseAsync(LabApiConstants.LabInfoEndpoint + user.LabName).ConfigureAwait(false);
+ var labInfoResponse = await GetLabResponseAsync(InternalConstants.LabInfoEndpoint + user.LabName).ConfigureAwait(false);
Lab[] labs = JsonConvert.DeserializeObject(labInfoResponse);
user.TenantId = labs[0].TenantId;
@@ -78,67 +88,67 @@ private Task RunQueryAsync(UserQuery query)
//Required parameters will be set to default if not supplied by the test code
queryDict.Add(
- LabApiConstants.MultiFactorAuthentication,
+ InternalConstants.MultiFactorAuthentication,
query.MFA != null ?
query.MFA.ToString() :
MFA.None.ToString());
queryDict.Add(
- LabApiConstants.ProtectionPolicy,
+ InternalConstants.ProtectionPolicy,
query.ProtectionPolicy != null ?
query.ProtectionPolicy.ToString() :
ProtectionPolicy.None.ToString());
if (query.UserType != null)
{
- queryDict.Add(LabApiConstants.UserType, query.UserType.ToString());
+ queryDict.Add(InternalConstants.UserType, query.UserType.ToString());
}
if (query.HomeDomain != null)
{
- queryDict.Add(LabApiConstants.HomeDomain, query.HomeDomain.ToString());
+ queryDict.Add(InternalConstants.HomeDomain, query.HomeDomain.ToString());
}
if (query.HomeUPN != null)
{
- queryDict.Add(LabApiConstants.HomeUPN, query.HomeUPN.ToString());
+ queryDict.Add(InternalConstants.HomeUPN, query.HomeUPN.ToString());
}
if (query.B2CIdentityProvider != null)
{
- queryDict.Add(LabApiConstants.B2CProvider, query.B2CIdentityProvider.ToString());
+ queryDict.Add(InternalConstants.B2CProvider, query.B2CIdentityProvider.ToString());
}
if (query.FederationProvider != null)
{
- queryDict.Add(LabApiConstants.FederationProvider, query.FederationProvider.ToString());
+ queryDict.Add(InternalConstants.FederationProvider, query.FederationProvider.ToString());
}
if (query.AzureEnvironment != null)
{
- queryDict.Add(LabApiConstants.AzureEnvironment, query.AzureEnvironment.ToString());
+ queryDict.Add(InternalConstants.AzureEnvironment, query.AzureEnvironment.ToString());
}
if (query.SignInAudience != null)
{
- queryDict.Add(LabApiConstants.SignInAudience, query.SignInAudience.ToString());
+ queryDict.Add(InternalConstants.SignInAudience, query.SignInAudience.ToString());
}
if (query.AppPlatform != null)
{
- queryDict.Add(LabApiConstants.AppPlatform, query.AppPlatform.ToString());
+ queryDict.Add(InternalConstants.AppPlatform, query.AppPlatform.ToString());
}
if (query.PublicClient != null)
{
- queryDict.Add(LabApiConstants.PublicClient, query.PublicClient.ToString());
+ queryDict.Add(InternalConstants.PublicClient, query.PublicClient.ToString());
}
- return SendLabRequestAsync(LabApiConstants.LabEndPoint, queryDict);
+ return SendLabRequestAsync(InternalConstants.LabEndPoint, queryDict);
}
else
{
- return SendLabRequestAsync(LabApiConstants.LabEndPoint + "/" + query.Upn, queryDict);
+ return SendLabRequestAsync(InternalConstants.LabEndPoint + "/" + query.Upn, queryDict);
}
}
@@ -159,7 +169,7 @@ private async Task SendLabRequestAsync(string requestUrl, Dictionary GetLabResponseAsync(string address)
{
if (_labApiAccessToken == null)
- _labApiAccessToken = await LabAuthenticationHelper.GetAccessTokenForLabAPIAsync(_labAccessAppId).ConfigureAwait(false);
+ _labApiAccessToken = await LabAuthenticationHelper.GetAccessTokenForLabAPIAsync().ConfigureAwait(false);
using (HttpClient httpClient = new HttpClient())
{
@@ -168,27 +178,17 @@ internal async Task GetLabResponseAsync(string address)
}
}
- public async Task GetUserSecretAsync(string lab)
+ internal async Task GetUserSecretAsync(string lab)
{
Dictionary queryDict = new Dictionary
{
{ "secret", lab }
};
- string result = await SendLabRequestAsync(LabApiConstants.LabUserCredentialEndpoint, queryDict).ConfigureAwait(false);
+ string result = await SendLabRequestAsync(InternalConstants.LabUserCredentialEndpoint, queryDict).ConfigureAwait(false);
return JsonConvert.DeserializeObject(result).Secret;
}
- 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
index c539d11223..428e993ebc 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceParameters.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/LabServiceParameters.cs
@@ -44,14 +44,14 @@ public enum UserType
MSA,
}
- public enum MFA
+ internal enum MFA
{
None,
MfaOnAll,
AutoMfaOnAll
}
- public enum ProtectionPolicy
+ internal enum ProtectionPolicy
{
None,
CA,
@@ -63,7 +63,7 @@ public enum ProtectionPolicy
MAMSPO
}
- public enum HomeDomain //Must add ".com" to end for lab query
+ internal enum HomeDomain //Must add ".com" to end for lab query
{
None,
MsidLab2,
@@ -71,7 +71,7 @@ public enum ProtectionPolicy
MsidLab4
}
- public enum HomeUPN //Must replace "_" with "@" add ".com" to end for lab query
+ internal enum HomeUPN //Must replace "_" with "@" add ".com" to end for lab query
{
None,
GidLab_Msidlab2,
@@ -89,20 +89,20 @@ public enum AzureEnvironment
azureusgovernment
}
- public enum SignInAudience
+ internal enum SignInAudience
{
AzureAdMyOrg,
AzureAdMultipleOrgs,
AzureAdAndPersonalMicrosoftAccount
}
- public enum AppPlatform
+ internal enum AppPlatform
{
web,
spa
}
- public enum PublicClient
+ internal enum PublicClient
{
yes,
no
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUser.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabUser.cs
index c3b09f5e40..34943c3b1f 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUser.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/LabUser.cs
@@ -22,13 +22,13 @@ public class LabUser
public string DisplayName { get; set; }
[JsonProperty("mfa")]
- public MFA Mfa { get; set; }
+ internal MFA Mfa { get; set; }
[JsonProperty("protectionpolicy")]
- public ProtectionPolicy ProtectionPolicy { get; set; }
+ internal ProtectionPolicy ProtectionPolicy { get; set; }
[JsonProperty("homedomain")]
- public HomeDomain HomeDomain { get; set; }
+ internal HomeDomain HomeDomain { get; set; }
[JsonProperty("homeupn")]
public string HomeUPN { get; set; }
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserHelper.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserHelper.cs
index 46017928c0..8af01235c4 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserHelper.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserHelper.cs
@@ -1,31 +1,48 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-using System;
+using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading.Tasks;
+using Azure;
namespace Microsoft.Identity.Test.LabInfrastructure
{
public static class LabUserHelper
{
- private static readonly LabServiceApi s_labService;
+ private static readonly LabServiceApi s_labService = new LabServiceApi();
private static readonly ConcurrentDictionary s_userCache =
new ConcurrentDictionary();
- public static KeyVaultSecretsProvider KeyVaultSecretsProviderMsal { get; }
- public static KeyVaultSecretsProvider KeyVaultSecretsProviderMsid { get; }
+ public static KeyVaultSecretsProvider KeyVaultSecretsProviderMsal { get; private set; }
+ public static KeyVaultSecretsProvider KeyVaultSecretsProviderMsid { get; private set; }
+
+ private static bool _isInitialized = false;
+ private static readonly object _initializationLock = new object();
- static LabUserHelper()
+ public static void Initialize()
{
- KeyVaultSecretsProviderMsal = new KeyVaultSecretsProvider(KeyVaultInstance.MsalTeam);
- KeyVaultSecretsProviderMsid = new KeyVaultSecretsProvider(KeyVaultInstance.MSIDLab);
- s_labService = new LabServiceApi();
+ if (_isInitialized)
+ {
+ return;
+ }
+
+ lock (_initializationLock)
+ {
+ if (_isInitialized)
+ {
+ return;
+ }
+
+ KeyVaultSecretsProviderMsal = new KeyVaultSecretsProvider(KeyVaultInstance.MsalTeam);
+ KeyVaultSecretsProviderMsid = new KeyVaultSecretsProvider(KeyVaultInstance.MSIDLab);
+
+ _isInitialized = true;
+ }
}
- public static async Task GetLabUserDataAsync(UserQuery query)
+ internal static async Task GetLabUserDataAsync(UserQuery query)
{
+ Initialize();
+
if (s_userCache.ContainsKey(query))
{
Trace.WriteLine("Lab user cache hit. Selected user: " + s_userCache[query].User.Upn);
@@ -35,7 +52,7 @@ public static async Task GetLabUserDataAsync(UserQuery query)
var response = await s_labService.GetLabResponseFromApiAsync(query).ConfigureAwait(false);
if (response == null)
{
- throw new LabUserNotFoundException(query, "Found no users for the given query.");
+ throw new LabUserNotFoundException("Found no users for the given query: " + query);
}
bool added = s_userCache.TryAdd(query, response);
@@ -53,23 +70,16 @@ public static Task GetLabUserDataForSpecificUserAsync(string upn)
public static async Task GetMSIEnvironmentVariablesAsync(string uri)
{
+ Initialize();
string result = await s_labService.GetLabResponseAsync(uri).ConfigureAwait(false);
return result;
}
- ///
- /// Returns the AAD cloud user idlab1@msidlab4.onmicrosoft.com
- ///
- ///
public static Task GetDefaultUserAsync()
{
return GetLabUserDataAsync(UserQuery.PublicAadUserQuery);
}
- ///
- /// Returns the AAD cloud user idlab@msidlab4.onmicrosoft.com
- ///
- ///
public static Task GetDefaultUser2Async()
{
return GetLabUserDataAsync(UserQuery.PublicAadUser2Query);
@@ -123,6 +133,17 @@ public static Task GetArlingtonUserAsync()
return response;
}
+ public static Task GetCiamUserAync()
+ {
+ var query = new UserQuery()
+ {
+ FederationProvider = FederationProvider.CIAMCUD,
+ SignInAudience = SignInAudience.AzureAdMyOrg
+ };
+
+ return GetLabUserDataAsync(query);
+ }
+
public static Task GetArlingtonADFSUserAsync()
{
var query = UserQuery.ArlingtonUserQuery;
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserNotFoundException.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserNotFoundException.cs
index 07ecf2a875..577c46cf05 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserNotFoundException.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/LabUserNotFoundException.cs
@@ -7,11 +7,15 @@ namespace Microsoft.Identity.Test.LabInfrastructure
{
public class LabUserNotFoundException : Exception
{
- public UserQuery Parameters { get; set; }
+
+ public LabUserNotFoundException(string message)
+ : base(message)
+ {
+ }
- public LabUserNotFoundException(UserQuery parameters, string message):base(message)
+ public LabUserNotFoundException(string message, Exception innerException)
+ : base(message, innerException)
{
- Parameters = parameters;
}
}
}
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/Microsoft.Identity.Test.LabInfrastructure.csproj b/tests/Microsoft.Identity.Test.LabInfrastructure/Microsoft.Identity.Test.LabInfrastructure.csproj
index 7c8ed47cba..9c01270ec9 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/Microsoft.Identity.Test.LabInfrastructure.csproj
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/Microsoft.Identity.Test.LabInfrastructure.csproj
@@ -8,20 +8,13 @@
+
+
-
- {3433eb33-114a-4db7-bc57-14f17f55da3c}
- Microsoft.Identity.Client
-
-
-
-
-
-
- Always
-
+
+
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/UserQueryParameters.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/UserQueryParameters.cs
index 3d11b80025..5cc176cf00 100644
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/UserQueryParameters.cs
+++ b/tests/Microsoft.Identity.Test.LabInfrastructure/UserQueryParameters.cs
@@ -1,12 +1,9 @@
// 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
+ internal struct UserQuery
{
public UserType? UserType { get; set; }
public MFA? MFA { get; set; }
@@ -78,5 +75,10 @@ public struct UserQuery
SignInAudience = LabInfrastructure.SignInAudience.AzureAdMyOrg
};
+
+ public override string ToString()
+ {
+ return $"UserType: {UserType}, MFA: {MFA}, ProtectionPolicy: {ProtectionPolicy}, HomeDomain: {HomeDomain}, HomeUPN: {HomeUPN}, B2CIdentityProvider: {B2CIdentityProvider}, FederationProvider: {FederationProvider}, AzureEnvironment: {AzureEnvironment}, SignInAudience: {SignInAudience}, AppPlatform: {AppPlatform}, PublicClient: {PublicClient}, Upn: {Upn}";
+ }
}
}
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/UserType.cs b/tests/Microsoft.Identity.Test.LabInfrastructure/UserType.cs
deleted file mode 100644
index 86e69e2139..0000000000
--- a/tests/Microsoft.Identity.Test.LabInfrastructure/UserType.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-namespace Microsoft.Identity.Test.LabInfrastructure
-{
-
-}
diff --git a/tests/Microsoft.Identity.Test.LabInfrastructure/data.txt b/tests/Microsoft.Identity.Test.LabInfrastructure/data.txt
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/tests/Microsoft.Identity.Test.Unit/Microsoft.Identity.Test.Unit.csproj b/tests/Microsoft.Identity.Test.Unit/Microsoft.Identity.Test.Unit.csproj
index c5e90c1c03..c68730a538 100644
--- a/tests/Microsoft.Identity.Test.Unit/Microsoft.Identity.Test.Unit.csproj
+++ b/tests/Microsoft.Identity.Test.Unit/Microsoft.Identity.Test.Unit.csproj
@@ -70,6 +70,7 @@
+
$(DefineConstants);NET_CORE