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
) inHttpClient
instances created viaIHttpClientFactory
. - 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
andIConfidentialClientApplication
.
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();