Security is always A topic, because you have to maintain multiple gates. IIS and WCF is a good example of that. When you want to configure security settings for WCF – you’ll have to change the web.config file appropriately and … most probably the IIS configuration as well.
This post will serve me as a reminder as well on what I have to do in order to achieve the necessary results. So, let’s get to the topic.
The goal: To configure WCF service to allow only HTTPS and clients must be authenticated using client certificate using the basicHttpBinding (sounds simple, doesn’t it?).
Ok, the first things first – we need to configure basicHttpBinding to request SSL and request client certificates. For that we need to add binding section like this:
<basicHttpBinding> <binding name="SSLBinding"> <security mode="Transport"> <transport clientCredentialType="Certificate" /> </security> </binding> </basicHttpBinding>
Generally it means that we will be securing communications at Transport level and the client credentials will be Certificates.
Second, we want to have access to metadata and map the certificates to Windows accounts. For that we will need to configure behaviors section:
<behavior name="SSLBehavior"> <serviceMetadata httpsGetEnabled="true" /> <serviceDebug httpHelpPageEnabled="false" includeExceptionDetailInFaults="true" /> <serviceCredentials> <clientCertificate> <authentication certificateValidationMode="PeerOrChainTrust" mapClientCertificateToWindowsAccount="true" /> </clientCertificate> <windowsAuthentication includeWindowsGroups="true" allowAnonymousLogons="false" /> </serviceCredentials> </behavior>
After this one is done – there is the last step to configure the service itself. Nice and easy:
<service behaviorConfiguration="SSLBehavior" name="Namespace.Implementation"> <endpoint address=https://localhost/Implementation/Implementation.svc binding="basicHttpBinding" bindingConfiguration="SSLBinding" name="TheService" contract="Namespace.IContract"> <identity> <dns value="Server" /> <certificateReference x509FindType="FindBySubjectName" findValue="localhost" /> </identity> </endpoint> </service>
Setting up SSL with Windows Vista is too easy, just take a look: http://weblogs.asp.net/scottgu/archive/2007/04/06/tip-trick-enabling-ssl-on-iis7-using-self-signed-certificates.aspx
So far so good, but there is one more thing – to configure the SSL and map windows accounts to certificates. In Windows 2003 – there is a UI in the IIS management console, but You won’t find one in the Vista. Help comes from here: http://blogs.iis.net/ulad/archive/2007/01/19/vbscript-to-configure-one-to-one-client-certificate-mapping-on-iis7.aspx
It will configure your applicationHost.config file and add similar section:
<security> <access sslFlags="SslRequireCert,SslNegotiateCert" /> <authentication> <anonymousAuthentication enabled="true" /> <windowsAuthentication enabled="true" useKernelMode="true" /> <iisClientCertificateMappingAuthentication enabled="true" oneToOneCertificateMappingsEnabled="true"> <oneToOneMappings> <add enabled="true" userName="computerusername" password="[enc:AesProvider:Encrypted password:enc]" certificate="Certificate content" /> </oneToOneMappings></iisClientCertificateMappingAuthentication> </authentication> </security>
Now lets get back to the bad parts:
First, you probably already noted that the service configuration is missing the IMetadataExchange endpoint, which is usually added to the service configuration. If you’d leave it, then you would receive errors like: "The SSL settings for the service ‘None’ does not match those of the IIS ‘Ssl, SslNegotiateCert, SslRequireCert, SslMapCer".
Also, you will need to enable anonymous authentication, because otherwise you will receive something like: "Security settings for this service require ‘Anonymous’ Authentication but it is not enabled for the IIS application that hosts this service."
And finally, couple of references I’ve used when going through all these issues (big thanks to authors):