다음을 통해 공유


Negotiate v/s NTLM

Definitions:

Negotiate:  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.

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.

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

 

This is how challenge based authentication works (NTLM, BASIC Selected)

System.Net Information: 0 : [15824] AcquireCredentialsHandle(package  = NTLM, intent   = Outbound, authdata = System.Net.SafeSspiAuthDataHandle)

 

Stack

============

   at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule, String package, CredentialUse intent, SafeSspiAuthDataHandle& authdata)

   at System.Net.NTAuthentication.Initialize(Boolean isServer, String package, NetworkCredential credential, String spn, ContextFlags requestedContextFlags, ChannelBinding channelBinding)

   at System.Net.NTAuthentication..ctor(Boolean isServer, String package, NetworkCredential credential, String spn, ContextFlags requestedContextFlags, ContextAwareResult context, ChannelBinding channelBinding)

   at System.Net.NTAuthentication..ctor(String package, NetworkCredential networkCredential, SpnToken spnToken, WebRequest request, ChannelBinding channelBinding)

   --->at System.Net.NtlmClient.DoAuthenticate(String challenge, WebRequest webRequest, ICredentials credentials, Boolean preAuthenticate)

   --->at System.Net.NtlmClient.Authenticate(String challenge, WebRequest webRequest, ICredentials credentials)

   --->at System.Net.AuthenticationManagerDefault.Authenticate(String challenge, WebRequest request, ICredentials credentials)

 

 

This is how challenge based authentication works (Negotiate, NTLM, BASIC Selected)

===========

System.Net Information: 0 : [17644] AcquireCredentialsHandle(package  = Negotiate, intent   = Outbound, authdata = System.Net.SafeSspiAuthDataHandle)

    DateTime=2015-12-25T10:12:06.7823985Z

 

Callstack=  

   at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule, String package, CredentialUse intent, SafeSspiAuthDataHandle& authdata)

   at System.Net.NTAuthentication.Initialize(Boolean isServer, String package, NetworkCredential credential, String spn, ContextFlags requestedContextFlags, ChannelBinding channelBinding)

   at System.Net.NTAuthentication..ctor(Boolean isServer, String package, NetworkCredential credential, String spn, ContextFlags requestedContextFlags, ContextAwareResult context, ChannelBinding channelBinding)

   at System.Net.NTAuthentication..ctor(String package, NetworkCredential networkCredential, SpnToken spnToken, WebRequest request, ChannelBinding channelBinding)

   --->at System.Net.NegotiateClient.DoAuthenticate(String challenge, WebRequest webRequest, ICredentials credentials, Boolean preAuthenticate)

   --->at System.Net.NegotiateClient.Authenticate(String challenge, WebRequest webRequest, ICredentials credentials)

   --->at System.Net.AuthenticationManagerDefault.Authenticate(String challenge, WebRequest request, ICredentials credentials)

   at System.Net.AuthenticationState.AttemptAuthenticate(HttpWebRequest httpWebRequest, ICredentials authInfo

 

So all mystery lies within this method:

============

System.Net.AuthenticationManagerDefault.Authenticate(String challenge, WebRequest request, ICredentials credentials)

This method reads the servers challenge and decide which scheme will be used by client.

 

When to use what?

NTLM:  Good option to use on standalone/workgroup machines.

Negotiate: Good option to use on Domain/Network joined client machines.

Kerberos:

Advanced and highly secure authentication scheme for Network joined machines.

 

Note:

As we can see above, if Negotiate is selected along with NTLM and BASIC at IIS. Client will always pick the highest protocol and in this case NEGOTIATE scheme (internally token sent can be NTLM).

Like this:

Authorization: Negotiate TlRMTVNTUAADAAAAGAAYAIIAAABUAVQBmgAAAAAAAABYAAAAEgASAFgAAAAYABgAagAAABAAEADuAQAANYKI4gYBsR0AAAAPTDrRMsXwFwu0tIpp5EAEAWQAZgBmAHIAYQBkAG0AaQBuADEANgA5ADYAOQAtAEsASQBCAEIARQBZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG5b7SNAeavLgPYfUsUc2EBAQAAAAAAAIUnRQrjMdEBGzZAyJKwTz4AAAAAAgAQAEYASABGAEcARAAtAE4AVAABAA4ARgBTAC0AQQBQAFAANwAEABgAZgBpAG4AbgBlAGcAYQBuAC4AYwBvAG0AAwAoAGYAcwAtAGEAcABwADcALgBmAGkAbgBuAGUAZwBhAG4ALgBjAG8AbQAFABgAZgBpAG4AbgBlAGcAYQBuAC4AYwBvAG0ABwAIAIUnRQrjMdEBBgAEAAIAAAAIADAAMAAAAAAAAAAAAAAAADAAAFtbnjnjb9OP7hJ0W2ZOQ6ltA1SrydJ3x0a9GREZ+6LiCgAQAAAAAAAAAAAAAAAAAAAAAAAJADIASABUAFQAUAAvAGYAcwAtAGEAcABwADcALgBmAGkAbgBuAGUAZwBhAG4ALgBjAG8AbQAAAAAAAAAAAAAAAAA66vnSb1h9qY85OmxzJoVu

 

In SSPI terms, this means selecting (the call to AcquireCredentialsHandle to have) “Negotiate” instead of “NTLM”. 

  

When we need to use NTLM, we need to make sure Negotiate is not enabled on IIS hosting application.

  

This is now NTLM authentication works:

https://blogs.msdn.com/b/chiranth/archive/2013/09/21/ntlm-want-to-know-how-it-works.aspx

https://www.innovation.ch/personal/ronald/ntlm.html

Credential Cache:

https://msdn.microsoft.com/en-us/library/system.net.credentialcache(v=vs.110).aspx

The CredentialCache class stores credentials for multiple Internet resources. Applications that need to access multiple resources can store the credentials for those resources in a CredentialCache instance that then provides the proper set of credentials to the Internet resource when required. When the GetCredential method is called, it compares the Uniform Resource Identifier (URI) and authentication type provided with those stored in the cache and returns the first set of credentials that match.

 

So it’s good to use Credential Cache when at the application startup we want to set credentials for accessing multiple applications.

For challenge based authentication like BASIC and NTLM, when consuming the single web service, we can stick with below code:

NetworkCredential cred = new NetworkCredential(userName, pass, domain);

myProxy.Credentials = cred;

 

This code will create the token based on challenge received via server, usually BASIC or NTLM when talking to web service hosted on IIS.

 

On other side:

Below code will store the CREDENTIAL in cache for specific URL.

 NetworkCredential cred = new NetworkCredential(userName, pass, domain);

            CredentialCache cc = new CredentialCache();

            string url = System.Configuration.ConfigurationManager.AppSettings["url"].ToString();

            cc.Add(new Uri(url), "Negotiate", cred);

            cc.Add(new Uri(url), "NTLM", cred);

            cc.Add(new Uri(url), "Kerberos", cred);

            cc.Add(new Uri(url), "Digest", cred);

 myProxy.Credentials = cc;

 

Remember:

When the GetCredential method is called, it compares the Uniform Resource Identifier (URI) and authentication type provided with those stored in the cache and returns the first set of credentials that match.

 

If we still need to use Credential Cache then we need to use below code to make sure we have relevant credential in cache depending on challenge received via server.

            NetworkCredential cred = new NetworkCredential(userName, pass, domain);

            CredentialCache cc = new CredentialCache();

            string url = System.Configuration.ConfigurationManager.AppSettings["url"].ToString();

            cc.Add(new Uri(url), "Negotiate", cred);

            cc.Add(new Uri(url), "NTLM", cred);

            cc.Add(new Uri(url), "Kerberos", cred);

            cc.Add(new Uri(url), "Digest", cred);

            myProxy.Credentials = cc;

Also Remember, avoid using other schemes (like Negotiate, Kerberos, Digest), if server is only supposed to take NTLM...

 

Another important thing to remember is NTLM Token validation

Once token is received as part of final challenge from client, it is sent to DC for validation…

 

This is how it looks in Network traces from server side:

  

 

Initial request to DC:

 

 

Response from DC, indicates whether NTLM Token is valid or not…

 

 

 

And eventually based on result, application send a 200 back to client.

 

I assume we call it as Non Interactive Log on process:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa378779(v=vs.85).aspx

 

Noninteractive authentication is performed when an application uses the Security Support Provider Interface (SSPI) and a security package to establish a secure network connection.

Noninteractive authentication is the mechanism at work when a user connects to multiple machines on a network without having to re-enter logon information for each machine

 

Screenshot and Sample app:

https://onedrive.live.com/redir?resid=7A701D22BF5927B8\!2149\&authkey=\!ANuAVHH1iS3\_Dao\&ithint=folder%2cdocx 

 

I hope this helps on when to use which scheme and how configurations needs to be done at IIS level.

 

Thanks

Saurabh