How to avoid multiple 401 when using Windows authentication on HTTP.sys

740 views Asked by At

I have a Web API which uses .NET core 2.2 and HTTP.Sys. I've setup Windows authentication and I can see the 401 WWW-Negotiate challenge followed by 200 when the user is authorized.

Now I've performed the same request several times but I see the challenge is happening for every request, slowing down the system and affecting performance. My sample client:

var httpHandler = new HttpClientHandler
{
    UseDefaultCredentials = true,
    Proxy = new WebProxy
    {
        Address = new Uri("http://HOSTNAME:8888"),
    }
};

using (var client = new HttpClient(httpHandler))
{

client.BaseAddress = new Uri("http://HOSTNAME:5000/");
for (int i = 0; i < 10; i++)
{
    try
    {
        HttpResponseMessage response = client.GetAsync("api/user").Result;
        response.EnsureSuccessStatusCode();
        string result = response.Content.ReadAsStringAsync().Result;
        Console.WriteLine("Result: " + result);
    }
    catch (System.Exception ex)
    {
        Console.WriteLine(ex);
    }
}

I read that for IIS it seems you can use authPersistNonNTLM=true here, but I couldn't fine a similar setting for pure HTTP.sys. any idea?

Thanks,

1

There are 1 answers

4
Gabriel Luci On

I don't see any similar option in the HttpSysOptions class (the options you pass to HTTP.sys).

What might help is to not dispose your HttpClient (don't use using on it). HttpClient is thread-safe and is intended to be reused. In fact, you should keep a static reference to it and reuse it. There is a lengthy discussion of why here, but in short: if you don't, it won't reuse connections.

That might have something to do with why you're seeing this. But if that doesn't resolve it, monitor the traffic and see if the authentication details are being sent by the client on the first request. They should be, since you set UseDefaultCredentials, but if not, then that's your problem.

Update: You can also try setting the PreAuthenticate property on your HttpClientHandler:

var httpHandler = new HttpClientHandler
{
    UseDefaultCredentials = true,
    PreAuthenticate = true,
    Proxy = new WebProxy
    {
        Address = new Uri("http://HOSTNAME:8888"),
    }
};

According to the documentation, after the first successful authentication, it will send the credentials on all following requests to the same hosts, without waiting for a 401 challenge.