1313using System . IdentityModel . Tokens . Jwt ;
1414using System . Collections . Generic ;
1515
16- namespace Microsoft . Identity . Test . Integration . NetCore . HeadlessTests
16+ namespace Microsoft . Identity . Test . Integration . HeadlessTests
1717{
1818 /// <summary>
1919 /// The tests in this file are demonstrations of the various authentication flows outlined in the "FMI protocol spec v1.0" Section 3.2
@@ -26,28 +26,28 @@ namespace Microsoft.Identity.Test.Integration.NetCore.HeadlessTests
2626 public class FmiIntegrationTests
2727 {
2828 private byte [ ] _serializedCache ;
29- private const string Testslice = "dc=ESTSR-PUB-WUS-LZ1-TEST" ; //Updated slice for regional tests
30- private Dictionary < string , ( string , bool ) > TestsliceQueryParam = new Dictionary < string , ( string value , bool includeInCacheKey ) > { { "dc" , ( "ESTSR-PUB-WUS-LZ1-TEST" , false ) } } ;
3129 private const string AzureRegion = "westus3" ;
32- private const string TenantId = "f645ad92-e38d-4d1a-b510-d1b09a74a8ca" ; // MSIDLAB4 tenant (legacy)
33-
30+ private const string TenantId = "10c419d4-4a50-45b2-aa4e-919fb84df24f" ;
31+ private const string RmaClientId = "3bf56293-fbb5-42bd-a407-248ba7431a8c" ;
32+ private const string WebApiScope = "api://aa464f73-2868-4f67-b0e7-fc2f749e757f/.default" ;
33+ private const string ExpectedResourceAudience = "api://aa464f73-2868-4f67-b0e7-fc2f749e757f" ;
34+ private const string ExpectedFmiCredentialAudience = "a9dd8a2a-df54-4ae0-84f9-38c8d57e5265" ;
35+
3436 [ TestMethod ]
3537 //RMA getting FMI cred for a leaf entity or sub-RMA
3638 public async Task Flow1_Credential_From_Cert ( )
3739 {
3840 //Arrange
3941 X509Certificate2 cert = CertificateHelper . FindCertificateByName ( TestConstants . AutomationTestCertName ) ;
4042
41- //Fmi app/scenario parameters
42- var clientId = "4df2cbbb-8612-49c1-87c8-f334d6d065ad" ;
43+ //Fmi app/scenario parameters
4344 var scope = "api://AzureFMITokenExchange/.default" ;
4445
4546 //Act
4647 //Create application
4748 var confidentialApp = ConfidentialClientApplicationBuilder
48- . Create ( clientId )
49+ . Create ( RmaClientId )
4950 . WithAuthority ( "https://login.microsoftonline.com/" , TenantId )
50- . WithExtraQueryParameters ( TestsliceQueryParam ) //Enables MSAL to target ESTS Test slice
5151 . WithCertificate ( cert , sendX5C : true ) //sendX5c enables SN+I auth which is required for FMI flows
5252 . WithAzureRegion ( AzureRegion )
5353 . BuildConcrete ( ) ;
@@ -58,7 +58,7 @@ public async Task Flow1_Credential_From_Cert()
5858
5959 //Recording test data for Asserts
6060 string expectedFmiPathHash = "zm2n0E62zwTsnNsozptLsoOoB_C7i-GfpxHYQQINJUw" ;
61- var expectedExternalCacheKey = $ "{ clientId } _{ TenantId } _{ expectedFmiPathHash } _AppTokenCache"; // last part is the SHA256 of the fmi path
61+ var expectedExternalCacheKey = $ "{ RmaClientId } _{ TenantId } _{ expectedFmiPathHash } _AppTokenCache"; // last part is the SHA256 of the fmi path
6262 var appCacheAccess = confidentialApp . AppTokenCache . RecordAccess (
6363 ( args ) => Assert . AreEqual ( args . SuggestedCacheKey , expectedExternalCacheKey ) ) ;
6464
@@ -69,11 +69,11 @@ public async Task Flow1_Credential_From_Cert()
6969 . ConfigureAwait ( false ) ;
7070
7171 //Assert
72- var expectedInternalCacheKey = $ "-login.microsoftonline.com-atext-{ clientId } -{ TenantId } -{ scope } -{ expectedFmiPathHash } ". ToLowerInvariant ( ) ;
72+ var expectedInternalCacheKey = $ "-login.microsoftonline.com-atext-{ RmaClientId } -{ TenantId } -{ scope } -{ expectedFmiPathHash } ". ToLowerInvariant ( ) ;
7373 AssertResults ( authResult ,
7474 confidentialApp ,
7575 expectedInternalCacheKey ,
76- "a9dd8a2a-df54-4ae0-84f9-38c8d57e5265" ,
76+ ExpectedFmiCredentialAudience ,
7777 "SomeFmiPath/FmiCredentialPath" ) ;
7878 }
7979
@@ -84,15 +84,10 @@ public async Task Flow2_Token_From_CertTest()
8484 //Arrange
8585 X509Certificate2 cert = CertificateHelper . FindCertificateByName ( TestConstants . AutomationTestCertName ) ;
8686
87- //Fmi app/scenario parameters
88- var clientId = "4df2cbbb-8612-49c1-87c8-f334d6d065ad" ;
89- var scope = "3091264c-7afb-45d4-b527-39737ee86187/.default" ;
90-
9187 //Act
9288 var confidentialApp = ConfidentialClientApplicationBuilder
93- . Create ( clientId )
89+ . Create ( RmaClientId )
9490 . WithAuthority ( "https://login.microsoftonline.com/" , TenantId )
95- . WithExtraQueryParameters ( TestsliceQueryParam )
9691 . WithCertificate ( cert , sendX5C : true )
9792 . WithAzureRegion ( AzureRegion )
9893 . BuildConcrete ( ) ;
@@ -102,20 +97,20 @@ public async Task Flow2_Token_From_CertTest()
10297
10398 //Recording test data for Asserts
10499 string expectedFmiPathHash = "zm2n0E62zwTsnNsozptLsoOoB_C7i-GfpxHYQQINJUw" ;
105- var expectedExternalCacheKey = $ "{ clientId } _{ TenantId } _{ expectedFmiPathHash } _AppTokenCache";
100+ var expectedExternalCacheKey = $ "{ RmaClientId } _{ TenantId } _{ expectedFmiPathHash } _AppTokenCache";
106101 var appCacheAccess = confidentialApp . AppTokenCache . RecordAccess (
107102 ( args ) => Assert . AreEqual ( args . SuggestedCacheKey , expectedExternalCacheKey ) ) ;
108103
109- var authResult = await confidentialApp . AcquireTokenForClient ( new [ ] { scope } )
104+ var authResult = await confidentialApp . AcquireTokenForClient ( new [ ] { WebApiScope } )
110105 . WithFmiPath ( "SomeFmiPath/FmiCredentialPath" )
111106 . ExecuteAsync ( )
112107 . ConfigureAwait ( false ) ;
113108
114- var expectedInternalCacheKey = $ "-login.microsoftonline.com-atext-{ clientId } -{ TenantId } -{ scope } -{ expectedFmiPathHash } ". ToLowerInvariant ( ) ;
109+ var expectedInternalCacheKey = $ "-login.microsoftonline.com-atext-{ RmaClientId } -{ TenantId } -{ WebApiScope } -{ expectedFmiPathHash } ". ToLowerInvariant ( ) ;
115110 AssertResults ( authResult ,
116111 confidentialApp ,
117112 expectedInternalCacheKey ,
118- "3091264c-7afb-45d4-b527-39737ee86187" ,
113+ ExpectedResourceAudience ,
119114 "SomeFmiPath/FmiCredentialPath" ) ;
120115 }
121116
@@ -130,10 +125,9 @@ public async Task Flow3_FmiCredential_From_AnotherFmiCredential()
130125 var scope = "api://AzureFMITokenExchange/.default" ;
131126
132127 var confidentialApp = ConfidentialClientApplicationBuilder
133- . Create ( clientId )
128+ . Create ( "urn:microsoft:identity:fmi" )
134129 . WithAuthority ( "https://login.microsoftonline.com/" , TenantId )
135- . WithExtraQueryParameters ( TestsliceQueryParam )
136- . WithClientAssertion ( ( options ) => GetFmiCredentialFromRma ( options , Testslice ) )
130+ . WithClientAssertion ( ( options ) => GetFmiCredentialFromRma ( options ) )
137131 . WithAzureRegion ( AzureRegion )
138132 . BuildConcrete ( ) ;
139133
@@ -155,7 +149,7 @@ public async Task Flow3_FmiCredential_From_AnotherFmiCredential()
155149 AssertResults ( authResult ,
156150 confidentialApp ,
157151 expectedInternalCacheKey ,
158- "a9dd8a2a-df54-4ae0-84f9-38c8d57e5265" ,
152+ ExpectedFmiCredentialAudience ,
159153 "SomeFmiPath/Path" ) ;
160154 }
161155
@@ -173,8 +167,7 @@ public async Task Flow4_SubRma_FIC_From_FmiCredential()
173167 var confidentialApp = ConfidentialClientApplicationBuilder
174168 . Create ( clientId )
175169 . WithAuthority ( "https://login.microsoftonline.com/" , TenantId )
176- . WithExtraQueryParameters ( TestsliceQueryParam )
177- . WithClientAssertion ( ( options ) => GetFmiCredentialFromRma ( options , Testslice ) )
170+ . WithClientAssertion ( ( options ) => GetFmiCredentialFromRma ( options ) )
178171 . WithAzureRegion ( AzureRegion )
179172 . BuildConcrete ( ) ;
180173
@@ -196,7 +189,7 @@ public async Task Flow4_SubRma_FIC_From_FmiCredential()
196189 AssertResults ( authResult ,
197190 confidentialApp ,
198191 expectedInternalCacheKey ,
199- "3091264c-7afb-45d4-b527-39737ee86187" ,
192+ ExpectedResourceAudience ,
200193 "SomeFmiPath/Path" ) ;
201194 }
202195
@@ -207,14 +200,12 @@ public async Task Flow5_FmiToken_From_FmiCred()
207200 //Arrange
208201 X509Certificate2 cert = CertificateHelper . FindCertificateByName ( TestConstants . AutomationTestCertName ) ;
209202
210- var clientId = "urn:microsoft:identity:fmi" ;
211- var scope = "3091264c-7afb-45d4-b527-39737ee86187/.default" ;
203+ var clientId = "urn:microsoft:identity:fmi" ;
212204
213205 var confidentialApp = ConfidentialClientApplicationBuilder
214206 . Create ( clientId )
215207 . WithAuthority ( "https://login.microsoftonline.com/" , TenantId )
216- . WithExtraQueryParameters ( TestsliceQueryParam )
217- . WithClientAssertion ( ( options ) => GetFmiCredentialFromRma ( options , Testslice ) )
208+ . WithClientAssertion ( ( options ) => GetFmiCredentialFromRma ( options ) )
218209 . WithAzureRegion ( AzureRegion )
219210 . BuildConcrete ( ) ;
220211
@@ -227,37 +218,34 @@ public async Task Flow5_FmiToken_From_FmiCred()
227218 var appCacheAccess = confidentialApp . AppTokenCache . RecordAccess (
228219 ( args ) => Assert . AreEqual ( args . SuggestedCacheKey , expectedExternalCacheKey ) ) ;
229220
230- var authResult = await confidentialApp . AcquireTokenForClient ( new [ ] { scope } )
221+ var authResult = await confidentialApp . AcquireTokenForClient ( new [ ] { WebApiScope } )
231222 . WithFmiPath ( "SomeFmiPath/Path" )
232223 . ExecuteAsync ( )
233224 . ConfigureAwait ( false ) ;
234225
235- var expectedInternalCacheKey = $ "-login.microsoftonline.com-atext-{ clientId } -{ TenantId } -{ scope } -{ expectedFmiPathHash } ". ToLowerInvariant ( ) ;
226+ var expectedInternalCacheKey = $ "-login.microsoftonline.com-atext-{ clientId } -{ TenantId } -{ WebApiScope } -{ expectedFmiPathHash } ". ToLowerInvariant ( ) ;
236227 AssertResults ( authResult ,
237228 confidentialApp ,
238229 expectedInternalCacheKey ,
239- "3091264c-7afb-45d4-b527-39737ee86187" ,
230+ ExpectedResourceAudience ,
240231 "SomeFmiPath/Path" ) ;
241232 }
242233
243- private static async Task < string > GetFmiCredentialFromRma ( AssertionRequestOptions options , string eqParameters )
234+ private static async Task < string > GetFmiCredentialFromRma ( AssertionRequestOptions options )
244235 {
245236 //Fmi app/scenario parameters
246237 var clientId = "4df2cbbb-8612-49c1-87c8-f334d6d065ad" ;
247238 var scope = "api://AzureFMITokenExchange/.default" ;
248239
249240 X509Certificate2 cert = CertificateHelper . FindCertificateByName ( TestConstants . AutomationTestCertName ) ;
250241
251- #pragma warning disable CS0618 // Type or member is obsolete
252242 //Create application
253243 var confidentialApp = ConfidentialClientApplicationBuilder
254244 . Create ( clientId )
255245 . WithAuthority ( "https://login.microsoftonline.com/f645ad92-e38d-4d1a-b510-d1b09a74a8ca" , true )
256- . WithExtraQueryParameters ( eqParameters ) //Enables MSAL to target ESTS Test slice
257246 . WithCertificate ( cert , sendX5C : true ) //sendX5c enables SN+I auth which is required for FMI flows
258247 . WithAzureRegion ( AzureRegion )
259248 . BuildConcrete ( ) ;
260- #pragma warning restore CS0618 // Type or member is obsolete
261249
262250 //Acquire Token
263251 var authResult = await confidentialApp . AcquireTokenForClient ( new [ ] { scope } )
@@ -292,6 +280,10 @@ private void AssertResults(
292280 var token = confidentialApp . AppTokenCacheInternal . Accessor . GetAllAccessTokens ( ) . First ( ) ;
293281
294282 Assert . IsNotNull ( authResult ) ;
283+ if ( audience . EndsWith ( "/.default" ) )
284+ {
285+ audience = audience . Substring ( 0 , audience . Length - "/.default" . Length ) ;
286+ }
295287 Assert . AreEqual ( expectedAudience , audience ) ;
296288 Assert . IsTrue ( subject . Contains ( expectedFmiPath ) ) ;
297289 Assert . AreEqual ( expectedInternalCacheKey , token . CacheKey ) ;
0 commit comments