Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public async Task AcquireTokenToRegionalEndpointAsync(bool instanceDiscoveryEnab
// Arrange
var factory = new HttpSnifferClientFactory();
var settings = ConfidentialAppSettings.GetSettings(Cloud.PublicLegacy); // Use legacy config for regional tests

settings.InstanceDiscoveryEndpoint = instanceDiscoveryEnabled;
_confidentialClientApplication = BuildCCA(settings, factory);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Collections.Generic;
using Microsoft.Identity.Test.Integration.NetFx.Infrastructure;

namespace Microsoft.Identity.Test.Integration.NetCore.HeadlessTests
namespace Microsoft.Identity.Test.Integration.HeadlessTests
{
/// <summary>
/// The tests in this file are demonstrations of the various authentication flows outlined in the "FMI protocol spec v1.0" Section 3.2
Expand All @@ -26,28 +27,28 @@ namespace Microsoft.Identity.Test.Integration.NetCore.HeadlessTests
public class FmiIntegrationTests
{
private byte[] _serializedCache;
private const string Testslice = "dc=ESTSR-PUB-WUS-LZ1-TEST"; //Updated slice for regional tests
private Dictionary<string, (string, bool)> TestsliceQueryParam = new Dictionary<string, (string value, bool includeInCacheKey)> { { "dc", ("ESTSR-PUB-WUS-LZ1-TEST", false) } };
private const string AzureRegion = "westus3";
private const string TenantId = "f645ad92-e38d-4d1a-b510-d1b09a74a8ca"; // MSIDLAB4 tenant (legacy)

private const string TenantId = ConfidentialAppSettings.ID4SLab1TenantId;
private const string RmaClientId = "3bf56293-fbb5-42bd-a407-248ba7431a8c";
private const string WebApiScope = "api://aa464f73-2868-4f67-b0e7-fc2f749e757f/.default";
private const string ExpectedResourceAudience = "api://aa464f73-2868-4f67-b0e7-fc2f749e757f";
private const string ExpectedFmiCredentialAudience = "a9dd8a2a-df54-4ae0-84f9-38c8d57e5265";

[TestMethod]
//RMA getting FMI cred for a leaf entity or sub-RMA
public async Task Flow1_Credential_From_Cert()
{
//Arrange
X509Certificate2 cert = CertificateHelper.FindCertificateByName(TestConstants.AutomationTestCertName);

//Fmi app/scenario parameters
var clientId = "4df2cbbb-8612-49c1-87c8-f334d6d065ad";
//Fmi app/scenario parameters
var scope = "api://AzureFMITokenExchange/.default";

//Act
//Create application
var confidentialApp = ConfidentialClientApplicationBuilder
.Create(clientId)
.Create(RmaClientId)
.WithAuthority("https://login.microsoftonline.com/", TenantId)
.WithExtraQueryParameters(TestsliceQueryParam) //Enables MSAL to target ESTS Test slice
.WithCertificate(cert, sendX5C: true) //sendX5c enables SN+I auth which is required for FMI flows
.WithAzureRegion(AzureRegion)
.BuildConcrete();
Expand All @@ -58,7 +59,7 @@ public async Task Flow1_Credential_From_Cert()

//Recording test data for Asserts
string expectedFmiPathHash = "zm2n0E62zwTsnNsozptLsoOoB_C7i-GfpxHYQQINJUw";
var expectedExternalCacheKey = $"{clientId}_{TenantId}_{expectedFmiPathHash}_AppTokenCache"; // last part is the SHA256 of the fmi path
var expectedExternalCacheKey = $"{RmaClientId}_{TenantId}_{expectedFmiPathHash}_AppTokenCache"; // last part is the SHA256 of the fmi path
var appCacheAccess = confidentialApp.AppTokenCache.RecordAccess(
(args) => Assert.AreEqual(args.SuggestedCacheKey, expectedExternalCacheKey));

Expand All @@ -69,11 +70,11 @@ public async Task Flow1_Credential_From_Cert()
.ConfigureAwait(false);

//Assert
var expectedInternalCacheKey = $"-login.microsoftonline.com-atext-{clientId}-{TenantId}-{scope}-{expectedFmiPathHash}".ToLowerInvariant();
var expectedInternalCacheKey = $"-login.microsoftonline.com-atext-{RmaClientId}-{TenantId}-{scope}-{expectedFmiPathHash}".ToLowerInvariant();
AssertResults(authResult,
confidentialApp,
expectedInternalCacheKey,
"a9dd8a2a-df54-4ae0-84f9-38c8d57e5265",
ExpectedFmiCredentialAudience,
"SomeFmiPath/FmiCredentialPath");
}

Expand All @@ -84,15 +85,10 @@ public async Task Flow2_Token_From_CertTest()
//Arrange
X509Certificate2 cert = CertificateHelper.FindCertificateByName(TestConstants.AutomationTestCertName);

//Fmi app/scenario parameters
var clientId = "4df2cbbb-8612-49c1-87c8-f334d6d065ad";
var scope = "3091264c-7afb-45d4-b527-39737ee86187/.default";

//Act
var confidentialApp = ConfidentialClientApplicationBuilder
.Create(clientId)
.Create(RmaClientId)
.WithAuthority("https://login.microsoftonline.com/", TenantId)
.WithExtraQueryParameters(TestsliceQueryParam)
.WithCertificate(cert, sendX5C: true)
.WithAzureRegion(AzureRegion)
.BuildConcrete();
Expand All @@ -102,20 +98,20 @@ public async Task Flow2_Token_From_CertTest()

//Recording test data for Asserts
string expectedFmiPathHash = "zm2n0E62zwTsnNsozptLsoOoB_C7i-GfpxHYQQINJUw";
var expectedExternalCacheKey = $"{clientId}_{TenantId}_{expectedFmiPathHash}_AppTokenCache";
var expectedExternalCacheKey = $"{RmaClientId}_{TenantId}_{expectedFmiPathHash}_AppTokenCache";
var appCacheAccess = confidentialApp.AppTokenCache.RecordAccess(
(args) => Assert.AreEqual(args.SuggestedCacheKey, expectedExternalCacheKey));

var authResult = await confidentialApp.AcquireTokenForClient(new[] { scope })
var authResult = await confidentialApp.AcquireTokenForClient(new[] { WebApiScope })
.WithFmiPath("SomeFmiPath/FmiCredentialPath")
.ExecuteAsync()
.ConfigureAwait(false);

var expectedInternalCacheKey = $"-login.microsoftonline.com-atext-{clientId}-{TenantId}-{scope}-{expectedFmiPathHash}".ToLowerInvariant();
var expectedInternalCacheKey = $"-login.microsoftonline.com-atext-{RmaClientId}-{TenantId}-{WebApiScope}-{expectedFmiPathHash}".ToLowerInvariant();
AssertResults(authResult,
confidentialApp,
expectedInternalCacheKey,
"3091264c-7afb-45d4-b527-39737ee86187",
ExpectedResourceAudience,
"SomeFmiPath/FmiCredentialPath");
}

Expand All @@ -130,10 +126,9 @@ public async Task Flow3_FmiCredential_From_AnotherFmiCredential()
var scope = "api://AzureFMITokenExchange/.default";

var confidentialApp = ConfidentialClientApplicationBuilder
.Create(clientId)
.Create("urn:microsoft:identity:fmi")
.WithAuthority("https://login.microsoftonline.com/", TenantId)
.WithExtraQueryParameters(TestsliceQueryParam)
.WithClientAssertion((options) => GetFmiCredentialFromRma(options, Testslice))
.WithClientAssertion((options) => GetFmiCredentialFromRma(options))
.WithAzureRegion(AzureRegion)
.BuildConcrete();

Expand All @@ -155,7 +150,7 @@ public async Task Flow3_FmiCredential_From_AnotherFmiCredential()
AssertResults(authResult,
confidentialApp,
expectedInternalCacheKey,
"a9dd8a2a-df54-4ae0-84f9-38c8d57e5265",
ExpectedFmiCredentialAudience,
"SomeFmiPath/Path");
}

Expand All @@ -173,8 +168,7 @@ public async Task Flow4_SubRma_FIC_From_FmiCredential()
var confidentialApp = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority("https://login.microsoftonline.com/", TenantId)
.WithExtraQueryParameters(TestsliceQueryParam)
.WithClientAssertion((options) => GetFmiCredentialFromRma(options, Testslice))
.WithClientAssertion((options) => GetFmiCredentialFromRma(options))
.WithAzureRegion(AzureRegion)
.BuildConcrete();

Expand All @@ -196,7 +190,7 @@ public async Task Flow4_SubRma_FIC_From_FmiCredential()
AssertResults(authResult,
confidentialApp,
expectedInternalCacheKey,
"3091264c-7afb-45d4-b527-39737ee86187",
ExpectedResourceAudience,
"SomeFmiPath/Path");
}

Expand All @@ -207,14 +201,12 @@ public async Task Flow5_FmiToken_From_FmiCred()
//Arrange
X509Certificate2 cert = CertificateHelper.FindCertificateByName(TestConstants.AutomationTestCertName);

var clientId = "urn:microsoft:identity:fmi";
var scope = "3091264c-7afb-45d4-b527-39737ee86187/.default";
var clientId = "urn:microsoft:identity:fmi";

var confidentialApp = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority("https://login.microsoftonline.com/", TenantId)
.WithExtraQueryParameters(TestsliceQueryParam)
.WithClientAssertion((options) => GetFmiCredentialFromRma(options, Testslice))
.WithClientAssertion((options) => GetFmiCredentialFromRma(options))
.WithAzureRegion(AzureRegion)
.BuildConcrete();

Expand All @@ -227,37 +219,34 @@ public async Task Flow5_FmiToken_From_FmiCred()
var appCacheAccess = confidentialApp.AppTokenCache.RecordAccess(
(args) => Assert.AreEqual(args.SuggestedCacheKey, expectedExternalCacheKey));

var authResult = await confidentialApp.AcquireTokenForClient(new[] { scope })
var authResult = await confidentialApp.AcquireTokenForClient(new[] { WebApiScope })
.WithFmiPath("SomeFmiPath/Path")
.ExecuteAsync()
.ConfigureAwait(false);

var expectedInternalCacheKey = $"-login.microsoftonline.com-atext-{clientId}-{TenantId}-{scope}-{expectedFmiPathHash}".ToLowerInvariant();
var expectedInternalCacheKey = $"-login.microsoftonline.com-atext-{clientId}-{TenantId}-{WebApiScope}-{expectedFmiPathHash}".ToLowerInvariant();
AssertResults(authResult,
confidentialApp,
expectedInternalCacheKey,
"3091264c-7afb-45d4-b527-39737ee86187",
ExpectedResourceAudience,
"SomeFmiPath/Path");
}

private static async Task<string> GetFmiCredentialFromRma(AssertionRequestOptions options, string eqParameters)
private static async Task<string> GetFmiCredentialFromRma(AssertionRequestOptions options)
{
//Fmi app/scenario parameters
var clientId = "4df2cbbb-8612-49c1-87c8-f334d6d065ad";
var scope = "api://AzureFMITokenExchange/.default";

X509Certificate2 cert = CertificateHelper.FindCertificateByName(TestConstants.AutomationTestCertName);

#pragma warning disable CS0618 // Type or member is obsolete
//Create application
var confidentialApp = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority("https://login.microsoftonline.com/f645ad92-e38d-4d1a-b510-d1b09a74a8ca", true)
.WithExtraQueryParameters(eqParameters) //Enables MSAL to target ESTS Test slice
.WithCertificate(cert, sendX5C: true) //sendX5c enables SN+I auth which is required for FMI flows
.WithAzureRegion(AzureRegion)
.BuildConcrete();
#pragma warning restore CS0618 // Type or member is obsolete

//Acquire Token
var authResult = await confidentialApp.AcquireTokenForClient(new[] { scope })
Expand Down Expand Up @@ -292,6 +281,10 @@ private void AssertResults(
var token = confidentialApp.AppTokenCacheInternal.Accessor.GetAllAccessTokens().First();

Assert.IsNotNull(authResult);
if (audience.EndsWith("/.default"))
{
audience = audience.Substring(0, audience.Length - "/.default".Length);
}
Assert.AreEqual(expectedAudience, audience);
Assert.IsTrue(subject.Contains(expectedFmiPath));
Assert.AreEqual(expectedInternalCacheKey, token.CacheKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ public interface IConfidentialAppSettings

public class ConfidentialAppSettings
{
public const string ID4SLab1TenantId = "10c419d4-4a50-45b2-aa4e-919fb84df24f";

private class PublicCloudConfidentialAppSettings : IConfidentialAppSettings
{
// TODO: Tenant Migration - Migrated to new id4slab1 tenant for non-regional tests
// Regional tests still use legacy configuration due to AADSTS100007 restrictions
public string ClientId => UseAppIdUri? "api://54a2d933-8bf8-483b-a8f8-0a31924f3c1f" : "54a2d933-8bf8-483b-a8f8-0a31924f3c1f"; // MSAL-APP-AzureADMultipleOrgs in ID4SLAB1 tenant
public string ClientId => UseAppIdUri? "api://54a2d933-8bf8-483b-a8f8-0a31924f3c1f" : "3bf56293-fbb5-42bd-a407-248ba7431a8c"; // MSAL-APP-AzureADMultipleOrgs in ID4SLAB1 tenant

public string TenantId => "10c419d4-4a50-45b2-aa4e-919fb84df24f"; // ID4SLAB1 tenant
public string TenantId => ID4SLab1TenantId;

public string Environment => "login.microsoftonline.com";

Expand Down
Loading