To understand the windows authentication mechanism better please refer: http://msdn2.microsoft.com/en-us/library/aa480475.....
A Web Application and WCF web service on Windows XP, where the Web Application uses services provided by WCF layer. Further, the WCF (or coarse grained services) talks to various Web Services (or fine grained web services), massages the data received and pass it to Web Application. The Web Service that WCF connects is hosted on Windows 2003 with NTAuthenticationProviders in IIS metabase set as NTLM.
You can view the IIS metabase using a tool called METAEDIT (download from here). You can also check the NTAuthenticationProviders on the machine by using the following script:
cscript %systemdrive%\inetpub\adminscripts\adsutil.vbs get /w3svc/1/NTAuthenticationProviders
(here "1" is the web site sequence internal to IIS, for XP it will always by "1")
cscript %systemdrive%\inetpub\adminscripts\adsutil.vbs get /w3svc/NTAuthenticationProviders
Now when Web application makes a call to WCF with binding configured as Windows (i.e. basicHttpBinding with bindingConfiguration specifying <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows"></transport></security>) and WCF calls the fine grained web services with same bindingConfiguration an obvious error would be thrown - that Client authentication header was passed as Negotiate where as the Server authentication header received is NTLM. The solution to the problem is changing the clientCredentialType to Ntlm in the config file of the WCF layer for the binding that is utilized for connecting to fine grained web services.
But now when you run the Web Application again you will encounter the following error - Client authentication header was passed as Ntlm where as the Server authentication header received is NTLM. By looking it seem that client is passing Ntlm and server is expecting NTLM (note the case), but the real reason for this is that NTLM identity is not passed across virtual folders / remote processes when NTLM authentication is used, thus it fails.
The solutions to this (assuming you don't have control over the third party / fine grained web services) are:
- At WCF layer before making a call to fine grained service impersonate your windows identity (you need to specify the password and userName)
- In machine.config there is a tag <processModel>(read about processModel here) which let you configure IIS worker process settings. The default setting for this is <processModel autoConfig="true" />, you need to change it to <processModel userName="somedomain\someuser" password="somepassword" />
(can use any one though I would suggest the 2nd approach as there are no code changes)
Reset the IIS and now the Identity is able to flow from the WCF to fine grained web service as you explicitly impersonated the same before calling the service or at worker process level.
If you have a control over fine grained web services that are hosted on Windows Server 2003, configure the IIS to use Kerberos instead of NTLM, by setting the NTAuthenticationProvider property of IIS metabase to "Negotiate" or "Negotiate,NTLM". The command for the same:
cscript %systemdrive%\inetpub\adminscripts\adsutil.vbs set /w3svc/1/NTAuthenticationProviders "Negotiate,NTLM" (Where the no. 1 depends on the internal sequence used by IIS for different web sites)
As the Kerberos is enabled on Windows Server and following conditions are true for your IIS web site configurations:
• The IIS 6.0 Web site is part of an IIS application pool.
• The application pool is running under a local account or under a domain user account.
• The Web site is configured to use Integrated Windows authentication only.
Now try accessing the fine grained web service (from a web browser) you will receive the error
"HTTP Error 401.1 - Unauthorized: Access is denied due to invalid credentials.",
which is thrown after browser challenges you 3 times for supplying the credntials.
Assuming this is the case with all the conditions mentioned above are true,then when Integrated Windows authentication tries to use Kerberos, Kerberos authentication may not work. To use Kerberos authentication, a service must register its service principal name (SPN) under the account in the Active Directory directory service that the service is running under. By default, Active Directory registers the network basic input/output system (NetBIOS) computer name. Active Directory also permits the Network Service or the Local System account to use Kerberos.
To resolve this behavior when the application pool is running under a domain user account, set up an HTTP SPN with the NetBIOS name and the fully qualified domain name (FQDN) of the domain user account that the application pool is running under.
2. Start a command prompt, and then change to the directory where you installed Setspn.exe.
3. At the command prompt, type the following commands. Press ENTER after each command:
setspn.exe -a http/IIS_computer's_NetBIOS_name DomainName\UserName
setspn.exe -a http/IIS_computer's_FQDN DomainName\UserName
UserName is the user account that the application pool is running under.
This command can only be executed by domain administrators.
After you set the SPN for the HTTP service to the domain user account that the application pool is running under, you can successfully connect to the Web site without being prompted for your user credentials and WCF will also be able to connect to the fine grained web services.