Overriding MSAL's HttpClient with IHttpClientFactory

Increase the reliability of MSAL.NET with IHttpClientFactory, benefiting from automatic DNS lookup, TCP connection reuse, and HttpMessageHandler pipeline extensibility.

The default behavior of MSAL.NET is to create its own static singleton instance of HttpClient. This HttpClient is then shared among different instances of IPublicClientApplication and IConfidentialClientApplication and used to make HTTP requests for various authentication flows.

However, it is preferable to provide your own instance of HttpClient for performance, reliability, and control reasons, as recommended by Microsoft in their excellent documentation Guidelines for using HttpClient. By providing your own instance of HttpClient created via IHttpClientFactory, you benefit from the following advantages:

  • Periodic DNS lookup by SocketsHttpHandler in case the IP address of the remote server changes.
  • Automatic management of TCP connection reuse with pooling.
  • Extensibility of the HttpMessageHandler pipeline to add your own handlers via named options.
  • Extensibility of HttpClient configuration also via named options.
  • Integration of the logging system (ILogger) in HttpClient instances created via IHttpClientFactory.
  • The ability to mock the primary HTTP handler for unit tests without changing the code that creates the MSAL application instances.

You can find further details on these benefits in the following documentation pages:

Note that MSAL integration for the web with Microsoft.Identity.Web already uses IHttpClientFactory. Therefore, this article will primarily concern situations where you create your own instances of IPublicClientApplication and IConfidentialClientApplication.

To replace the default MSAL HttpClient, you need to use the WithHttpClientFactory method of the PublicClientApplicationBuilder and ConfidentialClientApplicationBuilder. This method accepts an implementation of IMsalHttpClientFactory:

public interface IMsalHttpClientFactory
{
    HttpClient GetHttpClient();
}

All you need to do is implement this interface and register it in your application’s service collection:

internal sealed class MsalHttpClientFactoryAdapter(IHttpClientFactory httpClientFactory) : IMsalHttpClientFactory
{
    public HttpClient GetHttpClient()
    {
        return httpClientFactory.CreateClient("Msal");
    }
}

// Dependency injection registration
services.AddHttpClient("Msal").ConfigureHttpClient(httpClient =>
{
    // Default MSAL settings:
    // https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/blob/4.61.3/src/client/Microsoft.Identity.Client/Http/HttpClientConfig.cs#L18-L20
    httpClient.MaxResponseContentBufferSize = 1024 * 1024;
    httpClient.DefaultRequestHeaders.Accept.Clear();
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
});

services.AddSingleton<MsalHttpClientFactoryAdapter>();

Then, you can use this implementation when building your MSAL public or confidential application:

var httpClientFactory = serviceProvider.GetRequiredService<MsalHttpClientFactoryAdapter>();

var app = PublicClientApplicationBuilder.Create("<yourClientId>")
    // [...] Your MSAL app setup
    .WithHttpClientFactory(httpClientFactory)
    .Build();
Licensed under CC BY 4.0
Ko-fi donations Buy me a coffee