What is NTLM/Authenticate/Negotiate web authentication

13.3k views Asked by At

I understand basic and digest authentication. But I've searched a lot and I'm struggling with NTLM, Authenticate, & Negotiate.

I think, correct me if I am wrong, that NTLM & Authenticate are two terms for the same protocol.

And negotiate is trying first NTLM, then falling back to digest, then falling back to basic to connect.

Is that correct? And if so where is a good example of how to connect in C# both for NTLM only and for negotiate.

I have two use cases. The first is I need to pull down a single file. So make a request, get an XML file as the response, read it down, done.

The second is querying OData so hundreds to thousands of web requests, each of which will provide JSON (or XML) as the response.

1

There are 1 answers

3
peeyush singh On BEST ANSWER

Microsoft Negotiate is a security support provider (SSP) that acts as an application layer between Security Support Provider Interface (SSPI) and the other SSPs. When an application calls into SSPI to log on to a network, it can specify an SSP to process the request. If the application specifies Negotiate, Negotiate analyzes the request and picks the best SSP to handle the request based on customer-configured security policy.

https://learn.microsoft.com/en-us/windows/desktop/secauthn/microsoft-negotiate

As given in the article Negotiate does not fall back to digest. In a way Negotiate is like Kerberos but with a default backup of NTLM

Currently, the Negotiate security package selects between Kerberos and NTLM. Negotiate selects Kerberos unless it cannot be used by one of the systems involved in the authentication or the calling application did not provide sufficient information to use Kerberos.

Windows Challenge/Response (NTLM) is the authentication protocol used on networks that include systems running the Windows operating system and on stand-alone systems.

Authenticate is just an internal method, not sure why you are getting confused with it and the protocols, a good look at the internals is here: https://blogs.msdn.microsoft.com/dsnotes/2015/12/30/negotiate-vs-ntlm/

The way to look at this is:

  1. Microsoft came up initially with a way to authenticate on Windows servers/machine which they called NTLM , this used a request/response (sometimes called challenge) method.
  2. Subsequently they came up with a new protocol called Kerberos which was adopted.
  3. To make sure that existing application all function properly with old/new we have a new way to authenticate called Negotiate, which tried Kerberos and if that is not available goes for NTLM.

Edit 1 : Applying these authentication mechanisms for the Web was formalized in RFC 4559.

Edit 2 : NTLM authenticates one connection, not a request, while other authentication mechanisms usually authenticate one request. On the first use case this should not change so much, but for the second use case this makes sense to try NTLM while keeping one single connection (by using the HTTP Keep-Alive, and sending the credentials only once in the first request). There's maybe a performance difference. Keep us updated with your results.

A sample WebRequest code taken from Microsoft docs, you can replace the Webrequest with HttpWebRequest.

            // Create a request for the URL.   
            WebRequest request = WebRequest.Create(  
              "http://www.contoso.com/default.html");  
            // If required by the server, set the credentials.  
            request.Credentials = CredentialCache.DefaultCredentials;  
            // Get the response.  
            WebResponse response = request.GetResponse();  
            // Display the status.  
            Console.WriteLine (((HttpWebResponse)response).StatusDescription);  
            // Get the stream containing content returned by the server.  
            Stream dataStream = response.GetResponseStream();  
            // Open the stream using a StreamReader for easy access.  
            StreamReader reader = new StreamReader(dataStream);  
            // Read the content.  
            string responseFromServer = reader.ReadToEnd();  
            // Display the content.  
            Console.WriteLine(responseFromServer);  
            // Clean up the streams and the response.  
            reader.Close();  
            response.Close();