-
Notifications
You must be signed in to change notification settings - Fork 344
Retry Policy
MSAL.NET implements a simple retry-once mechanism for errors with HTTP error codes 500-600. For bigger availability, consider disabling the default retry policy and define your own, which takes into account the fact the service (AAD) may return a Retry-After header indicating to clients to pause for a few seconds.
Note: This sample is currently under review. You must use MSAL 4.47.2 or higher to use it.
public async Task<AuthenticationResult> GetTokenAsync()
{
var app = ConfidentialClientApplicationBuilder.Create(TestConstants.ClientId)
.WithClientSecret(TestConstants.ClientSecret)
.WithHttpClientFactory(
// consider using a higly scalable HttpClient, the default one is not great.
// See https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines#recommended-use
httpClientFactory: null,
// Disable MSAL's internal simple retry policy
retryOnceOn5xx: false)
.Build();
AsyncRetryPolicy retryPolicy = GetMsalRetryPolicy();
AuthenticationResult result = await retryPolicy.ExecuteAsync(
() => app.AcquireTokenForClient(TestConstants.s_scope.ToArray()).ExecuteAsync())
.ConfigureAwait(false);
return result;
}
private static AsyncRetryPolicy GetMsalRetryPolicy()
{
// Retry policy at token request level
TimeSpan retryAfter = TimeSpan.Zero;
var retryPolicy = Policy.Handle<Exception>(ex =>
{
return IsMsalRetryableException(ex, out retryAfter);
}).WaitAndRetryAsync(new[] // simple retry 0s, 3s, 5s + and "retry after" hint from the server
{
retryAfter, // could be 0
retryAfter + TimeSpan.FromSeconds(2),
retryAfter + TimeSpan.FromSeconds(5),
},
onRetry: (ex, ts) =>
// Do some logging
Debug.WriteLine($"MSAL call failed. Trying again after {ts}. Exception was {ex}"));
return retryPolicy;
}
/// <summary>
/// Retry any MsalException marked as retryable - see IsRetryiable property and HttpRequestException
/// If Retry-After header is present, return the value.
/// </summary>
/// <remarks>
/// In MSAL 4.47.2 IsRetryiable includes HTTP 408, 429 and 5xx AAD errors but may be expanded to transient AAD errors in the future.
/// </remarks>
private static bool IsMsalRetryableException(Exception ex, out TimeSpan retryAfter)
{
retryAfter = TimeSpan.Zero;
if (ex is HttpRequestException)
return true;
if (ex is MsalException msalException && msalException.IsRetryable)
{
if (msalException is MsalServiceException msalServiceException)
{
retryAfter = GetRetryAfterValue(msalServiceException.Headers);
}
return true;
}
return false;
}
private static TimeSpan GetRetryAfterValue(HttpResponseHeaders headers)
{
var date = headers?.RetryAfter?.Date;
if (date.HasValue)
{
return date.Value - DateTimeOffset.Now;
}
var delta = headers?.RetryAfter?.Delta;
if (delta.HasValue)
{
return delta.Value;
}
return TimeSpan.Zero;
}
When the Service Token Server (STS) is too busy or having problems, it returns an HTTP error 429. It may also return other HTTP error codes, such as 503. Alongside the response it will add a Retry-After header, which indicates that the client should wait before calling again. The wait delay is in seconds, as per spec.
MsalServiceException
surfaces System.Net.Http.Headers.HttpResponseHeaders
as a property named Headers
. You can therefore leverage additional information to the Error code to improve the reliability of your applications. In the case we just described, you can use the RetryAfter
property (of type RetryConditionHeaderValue
) and compute when to retry.
- Home
- Why use MSAL.NET
- Is MSAL.NET right for me
- Scenarios
- Register your app with AAD
- Client applications
- Acquiring tokens
- MSAL samples
- Known Issues
- AcquireTokenInteractive
- WAM - the Windows broker
- .NET Core
- Maui Docs
- Custom Browser
- Applying an AAD B2C policy
- Integrated Windows Authentication for domain or AAD joined machines
- Username / Password
- Device Code Flow for devices without a Web browser
- ADFS support
- Acquiring a token for the app
- Acquiring a token on behalf of a user in Web APIs
- Acquiring a token by authorization code in Web Apps
- High Availability
- Token cache serialization
- Logging
- Exceptions in MSAL
- Provide your own Httpclient and proxy
- Extensibility Points
- Clearing the cache
- Client Credentials Multi-Tenant guidance
- Performance perspectives
- Differences between ADAL.NET and MSAL.NET Apps
- PowerShell support
- Testing apps that use MSAL
- Experimental Features
- Proof of Possession (PoP) tokens
- Using in Azure functions
- Extract info from WWW-Authenticate headers
- SPA Authorization Code