Search code examples
c#asp.net-coredependency-injectiondotnet-httpclient

How to register HttpClient that will authenticate domain user


I have to configure HttpClient to automatically pass Windows credentials (company API that I'm calling is using Windows Authentication). So far I was creating HttpClient inside my methods like so:

var credentialsCache = new CredentialCache {{
  new Uri("https://localhost"),
  "NTLM",
  CredentialCache.DefaultNetworkCredentials
 }};
var handler = new HttpClientHandler { Credentials = credentialsCache };
var client = new HttpClient(handler);

but since this could lead to socket exhaustion I want to use factory. Therefore inside Startup.cs I would add HttpClient like so:

public void ConfigureServices(IServiceCollection services)
{
 // ...
 services.AddHttpClient();
}

Then I would inject factory into my service via constructor:

public class MyService
{
 private readonly IHttpClientFactory clientFactory;
 public MyService(IHttpClientFactory clientFactory)
 {
  this.clientFactory = clientFactory;
 }
 public async Task MakeHttpRequest()
 {
  var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost/endpoint");
  var client = clientFactory.CreateClient();
  var response = await client.SendAsync(request);
  // ...
 }
}

How can I configure client created this way to use network credentials? Ideally I would like to configure this only once, inside ConfigureServices()


Solution

  • You can use the options pattern to set configuration for how IHttpClientFactory creates the HttpClient. You can configure these options in the following ways

    Un-named options, these will apply to all instances of HttpClient that are created by the factory

    services.Configure<HttpClientFactoryOptions>(options =>
    {
        options.HttpMessageHandlerBuilderActions.Add(builder =>
        {
            var credentialsCache = new CredentialCache {{
                new Uri("https://localhost"),
                "NTLM",
                CredentialCache.DefaultNetworkCredentials
            }};
            builder.PrimaryHandler = new HttpClientHandler { Credentials = credentialsCache };
        });
    });
    

    Named options, these only apply to instances of HttpClient where you pass the name to the CreateClient method on the factory

    services.Configure<HttpClientFactoryOptions>("myclient", options =>
    {
        options.HttpMessageHandlerBuilderActions.Add(builder =>
        {
            var credentialsCache = new CredentialCache {{
                new Uri("https://localhost"),
                "NTLM",
                CredentialCache.DefaultNetworkCredentials
            }};
            builder.PrimaryHandler = new HttpClientHandler { Credentials = credentialsCache };
        });
    });
    

    To use the named options you would do

    var client = clientFactory.CreateClient("myclient");