Search code examples
c#httpclientntlmnegotiate

Can I avoid http challenge response?


We are using HttpClient to contact REST-services, which we know require NTLM or Negotiate authorization.

The problem is that HttpClient will first contact the service with no authorization (is that called challenge-response?). Client is rejected by the server with a 401, and only then will the client send the request to the server with an Authorization header.

Can we avoid this roundtrip by just adding the Authorization header on the first request?

We are creating out http-client like this (problem is the same with "NTLM" and "Negotiate"):

    public Rest.IRestClient Create()
    {
        var credentials = new CredentialCache { { _uri, "NTLM", CredentialCache.DefaultNetworkCredentials } };
    #if NETCOREAPP2_2
        var handler = new SocketsHttpHandler { Credentials = credentials, MaxConnectionsPerServer = 100, UseProxy = false };
    #elif NET461
        var handler = new WebRequestHandler { Credentials = credentials, UnsafeAuthenticatedConnectionSharing = true, MaxConnectionsPerServer = 100, UseProxy = false };
    #endif
        var httpClient = new HttpClient(handler) { BaseAddress = _uri, Timeout = _timeout };
        httpClient.DefaultRequestHeaders.ConnectionClose = false;
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(HostMediaTypeTranslator.GetMediaType(_hostMediaType)));
        if (_defaultRequestHeaders != null)
        {
            foreach (var header in _defaultRequestHeaders)
                httpClient.DefaultRequestHeaders.Add(header.Name, header.Value);
        }
        ServicePointManager.FindServicePoint(_uri).ConnectionLeaseTimeout = 120 * 1000;  // Close connection after two minutes
        return new Rest.RestClient(httpClient, _hostMediaType);
    }

Is it possible to just create our own NTLM or Kerberos token and add it as a header to the http-request?


Solution

  • No, because you are misunderstanding how NTLM works, and in particular the NTLM handshake.

    The initial 401 rejection response from the server also contains a challenge/nonce. The subsequent request from the client is requires to contain that challenge, encrypted with the hash of the authenticating account's password.

    This is how NTLM works and there is no way to get around it, because you don't (and intentionally can't) know the nonce the server is going to send.

    Reference: https://learn.microsoft.com/en-gb/windows/win32/secauthn/microsoft-ntlm