0

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,

peval27
  • 1,239
  • 2
  • 14
  • 40

1 Answers1

0

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.

Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • tried without disposing an the result is the same. BTW I am not disposing the client for each request, the same client is used for all 10 requests. – peval27 Sep 04 '19 at 07:06
  • I don't see any similar option to `authPersistNonNTLM`, so I'm not sure if that's possible. But if the client is sending credentials on the first request, then you still shouldn't get a 401. If you monitor the traffic, do you see the `Authorization` header sent on the first request? – Gabriel Luci Sep 04 '19 at 12:47
  • 1
    it seems to be a restriction in HTTP.SYS: https://github.com/aspnet/AspNetCore/issues/13634 – peval27 Sep 05 '19 at 09:08
  • 1
    I just updated my answer. I happened to stumble across the `PreAuthenticate` property today. It might help you here. – Gabriel Luci Sep 11 '19 at 02:50