Kerberos and NTLM Options for Integrated Windows Authentication iis 7.5

Integrated Windows authentication actually encompasses two different authentication protocols: Kerberos and Windows NT Challenge/Response, also known as NTLM. When this authentication protocol is enabled, IIS sends the following HTTP headers to the browser:

• WWW-Authenticate: Negotiate

• WWW-Authenticate: NTLM

Ref: http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/8feeaa51-c634-4de3-bfdc-e922d195a45e.mspx?mfr=true

 

 

WAS LOOKING FOR THIS ALL ALONG: Windows authentication supports two authentication protocols, Kerberos and NTLM, which are defined in the <providers> element. When you install and enable Windows authentication on IIS 7, the default protocol is Kerberos. The <windowsAuthentication> element can also contain a useKernelMode attribute that configures whether to use the kernel mode authentication feature that is new to Windows Server 2008. Ref:http://www.iis.net/configreference/system.webserver/security/authentication/windowsauthentication

 

 

The Negotiate header indicates that IIS can negotiate which of the two Windows authentication protocols to use. Internet Explorer 5, or later, recognizes this authentication header and determines which of the two authentication protocols to use. The NTLM authentication header is used as a fallback for browsers that do not support the Negotiate authentication header.

My Desktop Client, consuming a ASMX svc (Hosted on IIS with Windows Auth Enabled) was doing Kerberos Auth with the Server.

This is because, in the proxy class it says :

httpRequestToConnect.Credentials = CredentialCache.DefaultCredentials;

ALSO NOTE THAT THE ABOVE LINE OF CODE DOES THIS: http://stackoverflow.com/questions/19731347/where-does-defaultcredentials-pull-out-username-as-a-username-for-a-web-reques

The DefaultCredentials property applies only to NTLM, negotiate, and Kerberos-based authentication.

DefaultCredentials represents the system credentials for the current security context in which the application is running. For a client-side application, these are usually the Windows credentials

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

THIS WORKED WITH MY ASMX PROXY BUT WITH WCF, I HAVE TO CHAGE IT THIS WAY: http://social.msdn.microsoft.com/Forums/vstudio/en-US/0aac0110-187e-4a00-a597-f15b768cf16c/passing-client-credentials-to-wcf-service

 

Q : What is the role of active directory in Integrated Windows Authentication ?

Ans: IWA uses Kerberos that needs a KDB. AD is an eg. Of a KDB. Read on  : http://stackoverflow.com/questions/13767439/using-windows-authentication-with-active-directory-groups-as-roles

Further Reading:

  1. See: http://msdn.microsoft.com/en-us/library/ff648505.aspx for server side Configurations
  2. Impersonation Options : http://msdn.microsoft.com/en-us/library/ff647405.aspx
  3. http://wahlnetwork.com/2013/09/09/using-active-directory-integrated-windows-authentication-sso-5-5/ : I’ve used SPN in the past…

 

Advertisements

WCF and ASMX services and consuming using IP, Siteminder, Kerberos and SSL Authentication

WCF and
ASMX services and consuming using IP, Siteminder, Kerberos and SSL Authentication…

1.       Proxy

a.       Any type of Proxy (WCF or ASMX) can be created for a ASMX svc

b.      Any type of Proxy (WCF or ASMX) can be created for a WCF svc

2.       To create a proxy, we use VS..Create Ref…

3.       For WCF svc, use …/abc.svc?wsdl to get the wsdl (using which the proxy is generated)

4.       WCF Test Client is a tool to send request to wcf svc and invoke it

5.       For asmx svc u can use fiddler etc to invoke the svc.

6.       To consume a svc using its proxy all u have to do is to instanciate the Client : abcClient
svc = new abcClient(“abcBinding”, endpoint);

And call the remote method: svc.StringEcho(ref
testString); //Getting the response from the StringEcho method.

Authentication

The above pt 6 is valid when the svc does
not have any auth. Enabled, or maybe uses IP Auth.

But there are other auth mechanisms that
need the client to do special thigs:

A.
SITEMINDER
AUTH.

In the web.config, the following should be present:

A.      BINDING

                 <system.serviceModel>
                 <bindings>
                 <basicHttpBinding>
<!--For IP and SM Auth-->
                                   <binding name=" abcBinding " closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
                                            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                                            <security mode="None">
                                                     <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
                                                     <message clientCredentialType="UserName" algorithmSuite="Default"/>
                                            </security>

                        </binding>

</basicHttpBinding>

                          </bindings>
<client>
                          <!--For IP and SM Auth-->
                          <endpoint address="" contract="sdsde" name="abcBinding" binding="basicHttpBinding" bindingConfiguration="abcBinding" behaviorConfiguration="abcEndpointBehavior"/>
         </client>
                 <!--ForSiteminder-->
                 <extensions>
                          <behaviorExtensions>
                                   <add name="SMCookieBehavior" type="myNamespace.SM_BehaviorExtensionElement, Service Bus Checks, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
                          </behaviorExtensions>
                 </extensions>
                 <behaviors>
                          <endpointBehaviors>
                                   <behavior name="abcEndpointBehavior">
                                            <SMCookieBehavior asdf="test asdf"/>
                                   </behavior>                                 
                          </endpointBehaviors>
                 </behaviors>
         </system.serviceModel>

B.      Now
for SM auth the code is :

1.  add a Behavior and its Behavior Extension Element for SM Authentication
 
 namespace myNamespace 
{
public class SM_BehaviorExtensionElement : BehaviorExtensionElement
    {

        public override Type BehaviorType
        {
            get
            {
                return typeof(SM_EndpointBehavior);

            }
        }

 
 
        protected override object CreateBehavior()
        {
            return new SM_EndpointBehavior(asdf);
        }

        [ConfigurationProperty("asdf", IsRequired = true)]
        public string ASDF
        {
            get { return (string)base["asdf"]; }
            set { base["asdf"] = value; }
        }
    }
}
2.  Add an Endpoint  Behavior for SM Authentication
    public class SM_EndpointBehavior : IEndpointBehavior
    {
        private string m_asdf;
        public SM_EndpointBehavior(string asdf)
        {
           this.m_asdf = asdf;
        }
        #region IEndpointBehavior Members
        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {        }
        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            SM_UserAgentMessageInspector inspector = new SM_UserAgentMessageInspector(this.m_userAgent);
            clientRuntime.MessageInspectors.Add(inspector);
        }
          public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {}
         public void Validate(ServiceEndpoint endpoint)
        {}
        #endregion
    }
 
3.  Add a Message Inspector for SM Authentication
 public class SM_MessageInspector : IClientMessageInspector
    { 
        private const string USER_AGENT_HTTP_HEADER = "user-agent"; 
        private string m_asdf;
        public SM_UserAgentMessageInspector(string asdf)
        { 
           this.m_asdf = asdf; 
        }
 
       #region IClientMessageInspector Members
        public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {        }
        public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
        {
Console.log("in MessageInspector");
            }
            HttpRequestMessageProperty httpRequestMessage;

            object httpRequestMessageObject;

            if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
            {                
                httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;                
                HttpRequest Request = HttpContext.Current.Request;
                string SMCookie = null;
                SMCookie = Request.Headers["Cookie"];
                if (SMCookie != null)
                {
                    Console.write("SMCookie is :" + SMCookie);
                    httpRequestMessage.Headers["Cookie"] = SMCookie;
                    console.log("Cookie added :" + SMCookie);
                }
                else
                {
                   Console.write("SMCookie is null");
                }
            }

            else
            {                
                httpRequestMessage = new HttpRequestMessageProperty();
                HttpRequest Request = HttpContext.Current.Request;
                string SMCookie = null;
                SMCookie = Request.Headers["Cookie"];
                if (SMCookie != null)
                {
                    httpRequestMessage.Headers["Cookie"] = SMCookie;                
                }
                request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
            }
            return null;
        } 
        #endregion
    }

C.      To
consume a svc using its proxy over SM
all u have to do is to instanciate
the Client : abcClient svc = new abcClient(“abcBinding”, endpoint);

And call the remote method: svc.StringEcho(ref
testString); //Getting the response from the StringEcho method.

 

B.
KERBEROS
AUTH.

a.       For
this the client needs to do:

A.  WEB.CONFIG
<system.serviceModel>
                 <bindings>
                          <basicHttpBinding>
                                   <binding name="BasicHttpBinding_IKerberosService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
                                            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                                            <security mode="TransportCredentialOnly">
                                              <transport clientCredentialType="Windows" realm=""/>
                                              <message clientCredentialType="UserName" algorithmSuite="Default"/>
                                      </security>
                                   </binding>

Now Client:

<client>         
                          <!--For Kerberos Auth-->
                          <endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IKerberosService contract="abc.IKerberosService" name="BasicHttpBinding_IKerberosService">
                          </endpoint>

Now in code u have to do:

 EndpointIdentity identity = null;
                identity = EndpointIdentity.CreateSpnIdentity(“HTTP/a.b.com@p.q.r.COM”);
                string endpoint = “http:// a.b.com@p.q.r.COM:1234/abc/MyKerberosService.svc
”;

                EndpointAddress address = null;
                address = new EndpointAddress(new Uri(endpoint), identity);

                MyKerberosService Client client = new MyKerberosServiceClient("BasicHttpBinding_IKerberosService ", address);

                try
                {                    
                    String response = client.echoString("HELLO");

C.  SSL
AUTH

Web.config change:
<system.serviceModel>
                 <bindings>
                          <basicHttpBinding>
         <!--For SSL-->
                                   <binding name="abcSoap">
                                            <security mode="Transport">
                                                    <transport clientCredentialType="Certificate"/>
                                            </security>
                                   </binding>
Then
         <client>                  
                          <!--ForSSL-->
                          <endpoint address="" binding="basicHttpBinding" bindingConfiguration="GetFieldsMulRecSoap" contract="a.b" name="SSLAuthSvc"/>
                 </client>
Code :
1.   
        protected void validateCert(string CertSubject)
//HERE WE ARE SIMPLY ACCEPTING ALL THE SERVER SERTIFICATES THAT CONTAIN THE CERTIFICATE WE ARE LOOKING FOR USING CertSubject. THIS IS JUST BASIC VALIDATION. For PROPER VALIDATION, WE MAY WANT TO CHECK FOR SOME OTHER PROPERTY. Note that THE SERVER’S PUBLIC CERTI IS DEPLOYED IN 
        {
            //trust sender
            System.Net.ServicePointManager.ServerCertificateValidationCallback = ((sender, cert, chain, errors) => cert.Subject.Contains(CertSubject));
 //cert sub can be found from the cert props.It’s of format: a.b.com
Console.write(“Server Certificate Validated by Subject”);
 
        }
Main Code:
 string CertThumbprint = "12 12 41 c6 39 52 4e 59 6y 78 a6 2u c6 56";
string endpoint = “https://a.b.com:4208/p/q/r”;
var svc = new MySSLSvcClient(“SSLAuthSvc”, endpoint);
response = svc.myMethod(); 
svc.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, CertThumbprint);
 
//OK, SO WHAT WE ARE DOING HERE IS SIMPLY FINDING OUR OWN CERTIFICATE IN “StoreLocation.LocalMachine, StoreName.My”. NOTE THAT StoreName.My ACTUALLY REFERS TO PERSONAL FOLDER IN THE CERT STORE…
FINALLY WE ARE SENDING THE CERT WITH EVERY REQUEST
 
GENERAL DEPLOYMENT INSTRUCTIONSINSTALLATION:

1. Create a New Virtual Directory in IIS to host the site.
2. Create a new App Pool and run it under a sepcific service account (if needed)
3. Associate the VD with this App Pool
4. Convert the VD to Application from its Properties in intemgr.

 

DEPLOYMENT INSTRUCTIONS SPECIFIC TO CERT INSTALLATION:
  1. Install the
    Certificate of the Service Account under which the Application Will Run by
    running install.cmd*
  2. Next Install
    the Public Certificate of SERVER (Certificate Name: A.B.com.cer, in the location:
    storeName=”TrustedPeople” storeLocation=”LocalComputer”.

Note THAT IF YOU ARE RUNNING YOUR APPLICATION VD UNDER A SPECIFIC USER, CREATE A NEW APP
POOL AND IN THAT GIVE THE SPECIFIC  USER’S CREDENTIALS AND THEN RUN THE VD
UNDER THAT NEW APP POOL

ALSO, Add
the SPECIFIC USER account to the local IIS_WPG group.

* NOTE That
install.cmd is :

@echo off

certutil
-addstore ROOT QWER.cer  <THIS IS THE PARENT OF CLIENT CERTI>

certutil
-addstore ROOT ASDF.cer  <THIS IS THE PARENT OF SERVER CERTI>

call
“C:\Program Files\Windows Resource Kits\Tools\winhttpcertcfg” -i MY_CERT.pfx
-c LOCAL_MACHINE\MY -p test -a administrators

call
“C:\Program Files\Windows Resource Kits\Tools\winhttpcertcfg” -g -c
LOCAL_MACHINE\MY -s ” MY_CERT” -a MY_CERT

call
“C:\Program Files\Windows Resource Kits\Tools\winhttpcertcfg” -g -c
LOCAL_MACHINE\MY -s ” MY_CERT” -a Administrators

call
“C:\Program Files\Windows Resource Kits\Tools\winhttpcertcfg” -g -c
LOCAL_MACHINE\MY -s ” MY_CERT” -a System

call
“C:\Program Files\Windows Resource Kits\Tools\winhttpcertcfg” -l -c
LOCAL_MACHINE\MY -s ” MY_CERT”

pause