While prototyping a WCF service last week I ran into a number of confusing security-related errors on both the client and server. My setup was as follows:
- Windows 2008 Server
- IIS 7
- .NET 3.5
- basicHttpBinding/transport security/client certificates
Most of the errors that can result from this setup have been documented elsewhere. This detailed post by Imaya Kumar does a great job of walking through the overall configuration and explaining the error messages caused by various misconfigurations. However, I did run into one client error that wasn't specifically documented anywhere else:
System.ServiceModel.Security.MessageSecurityException: The HTTP request was forbidden with client authentication scheme 'Anonymous'. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden.
This error actually indicates that your client certificate could not be validated by the server. In my case I was using self-generated client and root certificates, and I had inadvertently uninstalled the root certificate from my server.
A related gotcha is that setting a particular clientCertificate.certificateValidationMode for your service is meaningless when using transport security. For example, the "PeerTrust" value in the configuration snippet below is ignored. Client certificates seem always to be validated using the PeerOrChainTrust method when using transport security with the http bindings.
1: <behaviors>
2: <serviceBehaviors>
3: <behavior name="TransportBehavior">
4: <serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="false" httpsHelpPageEnabled="true" />
5: <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
6: <serviceCredentials>
7: <clientCertificate>
8: <authentication certificateValidationMode="PeerTrust" />
9: </clientCertificate>
10: </serviceCredentials>
11: </behavior>
12: </serviceBehaviors>
13: </behaviors>