Skip to content

Commit 1e082d3

Browse files
authored
Fix ADFS tests for id4slab1 lab migration. (#5810)
* Re-enable ADFS tests for id4slab1 migration - Comment out MSAL_SKIP_FEDERATED_TESTS prop in Directory.Build.props so ADFS tests always run regardless of pipeline variable group - Update ADFSAuthority constant to point to fs.id4slab1.com (new lab) - Remove unused Adfs2019LabConstants class (no references in codebase) * Fix PopWhithAdfsUserAndBroker_Async cache environment after ADFS authority migration * Fix ADFS interactive Selenium test failures - UserInformationFieldIds.DetermineFieldIds: use OrdinalIgnoreCase for UserType comparisons. KeyVault stores 'federated' (lowercase) but LabConstants.UserTypeFederated is 'Federated', causing the case-sensitive == to fall through to AAD field IDs on an ADFS page (root cause). - InteractiveFlowTests.RunTestForUserAsync: use FindFreeLocalhostRedirectUri() for the non-direct path to avoid HttpListenerException port conflict with Interactive_Adfs_DirectAsync on localhost:52073. AAD public client apps accept any http://localhost:{port} so a dynamic port is valid here. * Fix all ADFS test failures for id4slab1 lab migration ClientCredentialsTests.NetFwk.cs: - Fix audience check: Contains('/adfs/') fails for authority without trailing slash. Changed to Contains('/adfs'). Bug introduced in a51b7f6 (Avery-Dunn, Jan 15 2026), never caught because IGNORE_FEDERATED was still gating tests. Also required server-side fixes on ADDC1 (cert in Root store + JWTSigningKey). UsernamePasswordIntegrationTests.NetFwk.cs: - Use AppAdfsNativeClient (ADFS NativeClientApplication GUID) instead of AppPCAClient (ServerApplication GUID). ADFS ServerApplications require client auth; public client ROPC flows need a NativeClientApplication registration. InteractiveFlowTests.NetFwk.cs: - Same AppAdfsNativeClient fix for Interactive_Adfs_DirectAsync. KeyVaultSecrets.cs: - Add AppAdfsNativeClient = 'App-AdfsNativeClient-Config' constant pointing to NativeClientApplication (c697bd8e-16d8-4f73-97d8-262e446581c2) registered in MSAL-Lab-Tests group on ADDC1. SeleniumExtensions.cs / UserInformationFieldIds.cs: - Simplify EnterPassword: remove redundant ADFS fallback logic (now handled upstream by DetermineFieldIds with OrdinalIgnoreCase comparison). Server-side changes on ADDC1 (permanent, not code): - NativeClientApplication 'MSAL-Lab-Client-Native' registered in MSAL-Lab-Tests - KV secret 'App-AdfsNativeClient-Config' created in id4skeyvault All 11 ADFS tests now pass locally (8 on NetCore, 3 on NetFx). * Restore tests/Directory.Build.props to match main (MSAL_SKIP_FEDERATED_TESTS == True) * Fix ADFS authority detection: use Uri path segment comparison instead of string.Contains
1 parent 96dc781 commit 1e082d3

8 files changed

Lines changed: 1691 additions & 1685 deletions

File tree

src/client/Microsoft.Identity.Lab.Api/Internal/TestConstants.cs

Lines changed: 1667 additions & 1667 deletions
Large diffs are not rendered by default.

src/client/Microsoft.Identity.Lab.Api/LabInfra/KeyVaultSecrets.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ public static class KeyVaultSecrets
5353
/// </summary>
5454
public const string AppPCAClient = "App-PCAClient-Config";
5555
/// <summary>
56+
/// Application configuration for ADFS native client testing scenarios. ADFS public client flows (ROPC, interactive)
57+
/// require a NativeClientApplication registration — ServerApplications reject them with MSIS9622.
58+
/// </summary>
59+
public const string AppAdfsNativeClient = "App-AdfsNativeClient-Config";
60+
/// <summary>
5661
/// Represents the configuration key for the application's Web API settings.
5762
/// </summary>
5863
public const string AppWebApi = "App-WebApi-Config";

src/client/Microsoft.Identity.Lab.Api/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const Microsoft.Identity.Test.Common.TestCategories.TokenCacheTests = "TokenCach
1313
const Microsoft.Identity.Test.Common.TestCategories.UnifiedSchemaValidation = "UnifiedSchema_Validation" -> string
1414
const Microsoft.Identity.Test.LabInfrastructure.KeyVaultInstance.MsalTeam = "https://id4skeyvault.vault.azure.net/" -> string
1515
const Microsoft.Identity.Test.LabInfrastructure.KeyVaultInstance.MSIDLab = "https://msidlabs.vault.azure.net" -> string
16+
const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppAdfsNativeClient = "App-AdfsNativeClient-Config" -> string
1617
const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppPCAClient = "App-PCAClient-Config" -> string
1718
const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppS2S = "App-S2S-Config" -> string
1819
const Microsoft.Identity.Test.LabInfrastructure.KeyVaultSecrets.AppWebApi = "App-WebApi-Config" -> string
@@ -50,7 +51,7 @@ const Microsoft.Identity.Test.Unit.TestConstants.ATSecret3 = "some-access-token3
5051
const Microsoft.Identity.Test.Unit.TestConstants.AadAuthorityWithMsftTenantId = "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/" -> string
5152
const Microsoft.Identity.Test.Unit.TestConstants.AadAuthorityWithTestTenantId = "https://login.microsoftonline.com/751a212b-4003-416e-b600-e1f48e40db9f/" -> string
5253
const Microsoft.Identity.Test.Unit.TestConstants.AadTenantId = "751a212b-4003-416e-b600-e1f48e40db9f" -> string
53-
const Microsoft.Identity.Test.Unit.TestConstants.ADFSAuthority = "https://fs.msidlab8.com/adfs/" -> string
54+
const Microsoft.Identity.Test.Unit.TestConstants.ADFSAuthority = "https://fs.id4slab1.com/adfs/" -> string
5455
const Microsoft.Identity.Test.Unit.TestConstants.ADFSAuthority2 = "https://someAdfs.com/adfs/" -> string
5556
const Microsoft.Identity.Test.Unit.TestConstants.AppServiceEndpoint = "http://127.0.0.1:41564/msi/token" -> string
5657
const Microsoft.Identity.Test.Unit.TestConstants.AuthorityCommonPpeAuthority = "https://login.windows-ppe.net/common/" -> string

tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/ClientCredentialsTests.NetFwk.cs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,13 @@ private static IConfidentialClientApplication CreateApp(
555555
.WithAuthority(authority, true)
556556
.WithTestLogging();
557557

558+
var authorityUri = new Uri(authority);
559+
bool isAdfs = authorityUri.AbsolutePath.Equals("/adfs", StringComparison.OrdinalIgnoreCase) ||
560+
authorityUri.AbsolutePath.StartsWith("/adfs/", StringComparison.OrdinalIgnoreCase);
561+
string adfsAud = isAdfs ?
562+
authority + "/oauth2/token" :
563+
authority + "/oauth2/v2.0/token";
564+
558565
switch (credentialType)
559566
{
560567
case CredentialType.Cert:
@@ -564,27 +571,18 @@ private static IConfidentialClientApplication CreateApp(
564571
builder.WithClientSecret(secret);
565572
break;
566573
case CredentialType.ClientAssertion_Manual:
567-
568-
var aud = authority.Contains("/adfs/") ?
569-
authority + "/oauth2/token" :
570-
authority + "/oauth2/v2.0/token";
571-
572574
builder.WithClientAssertion(() => GetSignedClientAssertionManual(
573575
clientId,
574-
aud, // for AAD use v2.0, but not for ADFS
576+
adfsAud, // for AAD use v2.0, but not for ADFS
575577
cert,
576578
useSha2AndPssForAssertion));
577579
break;
578580

579581
case CredentialType.ClientAssertion_Wilson:
580-
var aud2 = authority.Contains("/adfs/") ?
581-
authority + "/oauth2/token" :
582-
authority + "/oauth2/v2.0/token";
583-
584582
builder.WithClientAssertion(
585583
() => GetSignedClientAssertionUsingWilson(
586584
clientId,
587-
aud2,
585+
adfsAud,
588586
cert));
589587
break;
590588
#pragma warning disable CS0618 // Type or member is obsolete

tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/UsernamePasswordIntegrationTests.NetFwk.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public async Task ROPC_ADFSv4Federated_Async()
8080
public async Task AcquireTokenFromAdfsUsernamePasswordAsync()
8181
{
8282
var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserFederated).ConfigureAwait(false);
83-
var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false);
83+
var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppAdfsNativeClient).ConfigureAwait(false);
8484

8585
// Use the new ADFS authority and disable validation since ADFS infrastructure is not fully available
8686
Uri authorityUri = new Uri("https://fs.id4slab1.com/adfs");

tests/Microsoft.Identity.Test.Integration.netcore/Infrastructure/UserInformationFieldIds.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ public string AADUsernameInputId
6464

6565
private void DetermineFieldIds()
6666
{
67-
if (_user.UserType == LabConstants.UserTypeFederated)
67+
if (string.Equals(_user.UserType, LabConstants.UserTypeFederated, StringComparison.OrdinalIgnoreCase))
6868
{
6969
_passwordInputId = CoreUiTestConstants.AdfsV4WebPasswordId;
7070
_passwordSignInButtonId = CoreUiTestConstants.AdfsV4WebSubmitId;
7171
return;
7272
}
7373

74-
if (_user.UserType == LabConstants.UserTypeB2C)
74+
if (string.Equals(_user.UserType, LabConstants.UserTypeB2C, StringComparison.OrdinalIgnoreCase))
7575
{
7676
DetermineB2CFieldIds();
7777
return;

tests/Microsoft.Identity.Test.Integration.netcore/SeleniumTests/InteractiveFlowTests.NetFwk.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public async Task Interactive_Arlington_MultiCloudSupport_AADAsync()
138138
public async Task Interactive_Adfs_DirectAsync()
139139
{
140140
var user = await LabResponseHelper.GetUserConfigAsync(KeyVaultSecrets.UserFederated).ConfigureAwait(false);
141-
var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppPCAClient).ConfigureAwait(false);
141+
var app = await LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppAdfsNativeClient).ConfigureAwait(false);
142142
await RunTestForUserAsync(user, app, true).ConfigureAwait(false);
143143
}
144144

@@ -216,9 +216,11 @@ private async Task<AuthenticationResult> RunTestForUserAsync(UserConfig user, Ap
216216
}
217217
else
218218
{
219+
// Use a dynamic port to avoid conflicts when this test runs in parallel with Interactive_Adfs_DirectAsync,
220+
// which also listens on http://localhost:52073. AAD public client apps accept any http://localhost:{port}.
219221
pca = PublicClientApplicationBuilder
220222
.Create(app.AppId)
221-
.WithRedirectUri("http://localhost:52073")
223+
.WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri())
222224
.WithAuthority(app.Authority + "common")
223225
.WithTestLogging(out factory)
224226
.Build();

tests/Microsoft.Identity.Test.Unit/pop/PoPTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ public async Task PopWhithAdfsUserAndBroker_Async()
274274
PublicClientApplication pca = pcaBuilder.BuildConcrete();
275275

276276
TokenCacheHelper.PopulateCache(accessor: pca.UserTokenCacheInternal.Accessor,
277-
environment: "fs.msidlab8.com");
277+
environment: "fs.id4slab1.com");
278278
TokenCacheHelper.ExpireAllAccessTokens(pca.UserTokenCacheInternal);
279279

280280
pca.ServiceBundle.Config.BrokerCreatorFunc = (_, _, _) => mockBroker;

0 commit comments

Comments
 (0)