@@ -254,5 +254,45 @@ public async Task InstanceDiscoveryTimeout_FallsBackAndCachesResult_Async()
254254 Assert . AreEqual ( TokenSource . IdentityProvider , result2 . AuthenticationResultMetadata . TokenSource ) ;
255255 }
256256 }
257+
258+ [ TestMethod ]
259+ [ WorkItem ( 5805 ) ] // https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/5805
260+ public async Task InstanceDiscoveryCallerCancellation_BubblesUp_DoesNotFallBack_Async ( )
261+ {
262+ using ( var httpManager = new MockHttpManager ( disableInternalRetries : true ) )
263+ {
264+ // Arrange - use an authority unknown to MSAL so instance discovery goes to the network
265+ var app = ConfidentialClientApplicationBuilder . Create ( TestConstants . ClientId )
266+ . WithAuthority ( TestConstants . AuthorityNotKnownTenanted )
267+ . WithClientSecret ( TestConstants . ClientSecret )
268+ . WithHttpManager ( httpManager )
269+ . BuildConcrete ( ) ;
270+
271+ // Caller-controlled cancellation token
272+ using var callerCts = new CancellationTokenSource ( ) ;
273+
274+ // The mock GET handler for instance discovery: cancel the caller's token
275+ // during the request so that the linked CTS fires and the cancellation
276+ // propagates through the real linked-token path (not via ExceptionToThrow).
277+ httpManager . AddMockHandler ( new MockHttpMessageHandler ( )
278+ {
279+ ExpectedMethod = HttpMethod . Get ,
280+ ResponseMessage = new HttpResponseMessage ( HttpStatusCode . OK )
281+ {
282+ Content = new StringContent ( "{}" )
283+ } ,
284+ AdditionalRequestValidation = _ => callerCts . Cancel ( )
285+ } ) ;
286+
287+ // No token endpoint mock — the request should never get that far.
288+ // If it does, MockHttpManager will fail because the queue is empty.
289+
290+ // Act & Assert — caller cancellation must bubble up, not be swallowed
291+ // by the fallback catch in FetchNetworkMetadataOrFallbackAsync.
292+ await AssertException . TaskThrowsAsync < TaskCanceledException > (
293+ ( ) => app . AcquireTokenForClient ( TestConstants . s_scope . ToArray ( ) )
294+ . ExecuteAsync ( callerCts . Token ) ) . ConfigureAwait ( false ) ;
295+ }
296+ }
257297 }
258298}
0 commit comments