Monday 3 December 2012

SSL Mutual (Two-way) Authentication for WCF services in IIS 7.5 using client certificates

In a previous post, I described  how to configure SSL client Authentication in IIS 7.5 using a One-to-One Mapping.

In this post I describe how to set up a client authenticated WCF web service.

Firstly, there are three pre-requisites.
  1. Server Certificate from trusted CA.
  2. Client Certificate from trusted CA.
  3. WCF service deployed to a website that has been configured to use SSL, see this post for details on how to configure a website to use SSL.
I would suggest following my excellent series on CAs, which starts here, but alas it's mostly oriented for IIS 6, so it's not exactly terribly useful, it does create a CA which is the basis but not much more. Similarly, this post details the usage of makecert to create self-signed certificates but again it's geared towards IIS 6, the certificate generation commands will work though. You can also use openSSL, details here to create self-signed certificates.

In any case, the first step is to ensure that the website is set to require SSL and client certificates:


The second step is to enable Anonymous Authentication. This might sound like a bad idea and to a certain extent it is, using a one to one mapping is a better idea, but I've not got that working yet. What is achieved with this configuration is that any user that has a client certificate from a trusted CA will be be able to use the WCF service.



Third step is to change the configuration file of the WCF service to this (Use your own name and Contract):

  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="TransportSecurity">
          <security mode="Transport">
            <transport clientCredentialType="Certificate"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="API.Service" behaviorConfiguration="behaviour">
        <endpoint name="AnEndPoint" address="" binding="wsHttpBinding"
               contract="API.IService"  bindingConfiguration="TransportSecurity">
        </endpoint>
       </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="behaviour">
          <serviceMetadata   httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

And finally the client that consumes the web service needs to have this on the configuration file:

<system.serviceModel> 
 <bindings> 
  <wsHttpBinding> 
  <binding name="TransportSecurity"> 
   <security mode="Transport"> 
    <transport clientCredentialType="Certificate" /> 
   </security> 
  </binding> 
  </wsHttpBinding> 
 </bindings> 
 <client> 
  <endpoint address="https://fqdn/service.svc" behaviorConfiguration="behaviour" 
  binding="wsHttpBinding" bindingConfiguration="TransportSecurity" 
  contract="API.IService" name="TransportSecurity" /> 
 </client> 
 <behaviors> 
  <endpointBehaviors> 
   <behavior name="behaviour"> 
    <clientCredentials> 
     <clientCertificate findValue="577aeb8b603af8453b80c55e9ac4abdfd4cf9c6c" 
     storeLocation="CurrentUser" x509FindType="FindByThumbprint" />
    </clientCredentials> 
   </behavior> 
  </endpointBehaviors> 
 </behaviors> 
</system.serviceModel>

Note that you can also use a browser to test this.

No comments:

Post a Comment