WCF is very powerful and very, very complicated to configure in many cases. Seemingly simple requirements can get really difficult to get right and security definitely falls in that category. I recently had the following need:
- WCF-services hosted in IIS 7.5
- Windows authentication should be used for the services
- The client must not be required to be in the same domain as the service application
Simple enough, right? Not for me it wasn’t…
My first idea was to set the authentication settings in IIS to Windows Authentication and configure the client to use credentials from a config file, this was the method I’m used to when calling ASMX services, but it didn’t work. It was really frustrating as well as it’s so difficult to understand what’s going on.
No matter what changes I did in the configuration files, I kept getting errors such as
The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Negotiate,NTLM'.
I was finally able to come up with a solution which I thought I’d share with you. I don’t know if it’s optimal, but if you think it’s not then please leave a comment.
What I did was this:
- Disable IIS authentication by setting it to Anonymous in the IIS Manager
- In the binding configuration for the services, set security mode to Message and to use Windows Authentication:
<security mode="Message"> <message clientCredentialType="Windows" /> </security>
On the client side we now have the option to pass on the currently logged in user’s credentials (requires no extra handling, just call the service) or to explicitly give the credentials to use. The latter is done like this for a ClientBase<T> proxy:
client.ClientCredentials.Windows.ClientCredential.Domain = "xxx"; client.ClientCredentials.Windows.ClientCredential.UserName = "yyy"; client.ClientCredentials.Windows.ClientCredential.Password = "zzz"; client.MyMethod();
This solved the problem for me. I think the major difficulty I had was that IIS and WCF security settings collided, so I believe the lesson learned is to do security on only one place and that place should probably be WCF.
On a related note, I have also had problems with service discovery, WSDL, etc if the web application is not set to Anonymous authentication in IIS, so it seems to be a good idea to do it like that for that reason as well.