44using System ;
55using System . Linq ;
66using System . Globalization ;
7+ using System . Threading ;
78using System . Threading . Tasks ;
89using Microsoft . Identity . Client . Http ;
910using Microsoft . Identity . Client . OAuth2 ;
@@ -21,15 +22,24 @@ internal class NetworkMetadataProvider : INetworkMetadataProvider
2122 private readonly IHttpManager _httpManager ;
2223 private readonly INetworkCacheMetadataProvider _networkCacheMetadataProvider ;
2324 private readonly Uri _userProvidedInstanceDiscoveryUri ; // can be null
25+ private readonly int _instanceDiscoveryTimeoutMs ;
26+
27+ /// <summary>
28+ /// Default timeout for instance discovery network calls.
29+ /// Prevents waiting for the full HttpClient timeout (100s) when the discovery endpoint is unreachable.
30+ /// </summary>
31+ internal const int DefaultInstanceDiscoveryTimeoutMs = 10_000 ;
2432
2533 public NetworkMetadataProvider (
2634 IHttpManager httpManager ,
2735 INetworkCacheMetadataProvider networkCacheMetadataProvider ,
28- Uri userProvidedInstanceDiscoveryUri = null )
36+ Uri userProvidedInstanceDiscoveryUri = null ,
37+ int instanceDiscoveryTimeoutMs = DefaultInstanceDiscoveryTimeoutMs )
2938 {
3039 _httpManager = httpManager ?? throw new ArgumentNullException ( nameof ( httpManager ) ) ;
3140 _networkCacheMetadataProvider = networkCacheMetadataProvider ?? throw new ArgumentNullException ( nameof ( networkCacheMetadataProvider ) ) ;
3241 _userProvidedInstanceDiscoveryUri = userProvidedInstanceDiscoveryUri ; // can be null
42+ _instanceDiscoveryTimeoutMs = instanceDiscoveryTimeoutMs ;
3343 }
3444
3545 public async Task < InstanceDiscoveryMetadataEntry > GetMetadataAsync ( Uri authority , RequestContext requestContext )
@@ -83,11 +93,25 @@ private async Task<InstanceDiscoveryResponse> SendInstanceDiscoveryRequestAsync(
8393
8494 Uri instanceDiscoveryEndpoint = ComputeHttpEndpoint ( authority , requestContext ) ;
8595
86- InstanceDiscoveryResponse discoveryResponse = await client
87- . DiscoverAadInstanceAsync ( instanceDiscoveryEndpoint , requestContext )
88- . ConfigureAwait ( false ) ;
96+ using var timeoutCts = new CancellationTokenSource ( _instanceDiscoveryTimeoutMs ) ;
97+ using var linkedCts = CancellationTokenSource . CreateLinkedTokenSource (
98+ requestContext . UserCancellationToken , timeoutCts . Token ) ;
8999
90- return discoveryResponse ;
100+ CancellationToken originalToken = requestContext . UserCancellationToken ;
101+ requestContext . UserCancellationToken = linkedCts . Token ;
102+
103+ try
104+ {
105+ InstanceDiscoveryResponse discoveryResponse = await client
106+ . DiscoverAadInstanceAsync ( instanceDiscoveryEndpoint , requestContext )
107+ . ConfigureAwait ( false ) ;
108+
109+ return discoveryResponse ;
110+ }
111+ finally
112+ {
113+ requestContext . UserCancellationToken = originalToken ;
114+ }
91115 }
92116
93117 private Uri ComputeHttpEndpoint ( Uri authority , RequestContext requestContext )
0 commit comments