@@ -668,5 +668,73 @@ private static HttpResponseMessage CreateResponse(
668668 {
669669 return MockHelpers . CreateSuccessfulClientCredentialTokenResponseMessage ( token , expiresIn , tokenType ) ;
670670 }
671+
672+ [ TestMethod ]
673+ public async Task AcquireTokenForClient_WithMtlsPop_Dsts_SuccessAsync ( )
674+ {
675+ string authorityUrl = TestConstants . DstsAuthorityTenanted ;
676+
677+ // Modify the endpoint based on the authorityUrl
678+ string expectedTokenEndpoint = $ "{ authorityUrl } oauth2/v2.0/token";
679+
680+ using ( var httpManager = new MockHttpManager ( ) )
681+ {
682+ // Set up mock handler with expected token endpoint URL
683+ httpManager . AddMockHandler ( new MockHttpMessageHandler ( )
684+ {
685+ ExpectedUrl = expectedTokenEndpoint ,
686+ ExpectedMethod = HttpMethod . Post ,
687+ ResponseMessage = MockHelpers . CreateSuccessfulClientCredentialTokenResponseMessage ( tokenType : "mtls_pop" )
688+ } ) ;
689+
690+ var app = ConfidentialClientApplicationBuilder . Create ( TestConstants . ClientId )
691+ . WithCertificate ( s_testCertificate )
692+ . WithAuthority ( authorityUrl )
693+ . WithExperimentalFeatures ( )
694+ . WithHttpManager ( httpManager )
695+ . BuildConcrete ( ) ;
696+
697+ // First token acquisition - should hit the identity provider
698+ AuthenticationResult result = await app . AcquireTokenForClient ( TestConstants . s_scope )
699+ . WithMtlsProofOfPossession ( )
700+ . ExecuteAsync ( )
701+ . ConfigureAwait ( false ) ;
702+
703+ Assert . AreEqual ( "header.payload.signature" , result . AccessToken ) ;
704+ Assert . AreEqual ( Constants . MtlsPoPAuthHeaderPrefix , result . TokenType ) ;
705+ Assert . AreEqual ( null , result . AuthenticationResultMetadata . RegionDetails . RegionUsed ) ;
706+ Assert . AreEqual ( expectedTokenEndpoint , result . AuthenticationResultMetadata . TokenEndpoint ) ;
707+
708+ // Second token acquisition - should retrieve from cache
709+ AuthenticationResult secondResult = await app . AcquireTokenForClient ( TestConstants . s_scope )
710+ . WithMtlsProofOfPossession ( )
711+ . ExecuteAsync ( )
712+ . ConfigureAwait ( false ) ;
713+
714+ Assert . AreEqual ( "header.payload.signature" , secondResult . AccessToken ) ;
715+ Assert . AreEqual ( Constants . MtlsPoPAuthHeaderPrefix , secondResult . TokenType ) ;
716+ Assert . AreEqual ( TokenSource . Cache , secondResult . AuthenticationResultMetadata . TokenSource ) ;
717+ }
718+ }
719+
720+ [ TestMethod ]
721+ public async Task MtlsPopDstsCommonAuthorityFailsAsync ( )
722+ {
723+ IConfidentialClientApplication app = ConfidentialClientApplicationBuilder
724+ . Create ( TestConstants . ClientId )
725+ . WithAuthority ( TestConstants . DstsAuthorityCommon )
726+ . WithCertificate ( s_testCertificate )
727+ . WithExperimentalFeatures ( )
728+ . Build ( ) ;
729+
730+ // Set WithMtlsProofOfPossession on the request without specifying an authority
731+ MsalClientException ex = await AssertException . TaskThrowsAsync < MsalClientException > ( ( ) =>
732+ app . AcquireTokenForClient ( TestConstants . s_scope )
733+ . WithMtlsProofOfPossession ( )
734+ . ExecuteAsync ( ) )
735+ . ConfigureAwait ( false ) ;
736+
737+ Assert . AreEqual ( MsalError . MissingTenantedAuthority , ex . ErrorCode ) ;
738+ }
671739 }
672740}
0 commit comments