@@ -333,6 +333,56 @@ public async Task BadOidcResponse_ThrowsException_Async(string badOidcResponseTy
333333 }
334334 }
335335
336+ [ TestMethod ]
337+ public async Task OidcIssuerValidation_AcceptsDifferentPath_Async ( )
338+ {
339+ using ( var httpManager = new MockHttpManager ( ) )
340+ {
341+ // This test was made to cover an issue that realistically would only happen with Microsoft authorities in multi-tenant scenarios,
342+ // so it uses a Microsoft host instead of the custom domain used in other tests.
343+ string microsoftHost = "login.microsoftonline.com" ;
344+ string authority = $ "https://{ microsoftHost } /organizations/2.0/";
345+ string issuerWithDifferentPath = $ "https://{ microsoftHost } /someTenant/2.0/";
346+
347+ IConfidentialClientApplication app = ConfidentialClientApplicationBuilder
348+ . Create ( TestConstants . ClientId )
349+ . WithHttpManager ( httpManager )
350+ . WithOidcAuthority ( authority )
351+ . WithClientSecret ( TestConstants . ClientSecret )
352+ . Build ( ) ;
353+
354+ // Create OIDC document with a Microsoft host and an issuer that has matching host but different path
355+ string oidcDocumentWithDifferentPath = TestConstants . GenericOidcResponse . Replace (
356+ $ "\" issuer\" :\" { TestConstants . GenericAuthority } \" ",
357+ $ "\" issuer\" :\" { issuerWithDifferentPath } \" ") ;
358+ oidcDocumentWithDifferentPath = oidcDocumentWithDifferentPath . Replace (
359+ "demo.duendesoftware.com" ,
360+ microsoftHost ) ;
361+
362+ // Mock OIDC endpoint response
363+ httpManager . AddMockHandler ( new MockHttpMessageHandler
364+ {
365+ ExpectedMethod = HttpMethod . Get ,
366+ ExpectedUrl = $ "{ authority } { Constants . WellKnownOpenIdConfigurationPath } ",
367+ ResponseMessage = MockHelpers . CreateSuccessResponseMessage ( oidcDocumentWithDifferentPath )
368+ } ) ;
369+
370+ // Mock token endpoint response
371+ httpManager . AddMockHandler (
372+ CreateTokenResponseHttpHandler (
373+ $ "https://{ microsoftHost } /connect/token",
374+ scopesInRequest : "api" ,
375+ scopesInResponse : "api" ,
376+ grant : "client_credentials" ) ) ;
377+
378+ // Should not throw an exception with our updated validation
379+ var result = await app . AcquireTokenForClient ( new [ ] { "api" } ) . ExecuteAsync ( ) . ConfigureAwait ( false ) ;
380+
381+ Assert . IsNotNull ( result ) ;
382+ Assert . IsNotNull ( result . AccessToken ) ;
383+ }
384+ }
385+
336386 [ TestMethod ]
337387 public async Task OidcIssuerValidation_ThrowsForNonMatchingIssuer_Async ( )
338388 {
0 commit comments