WCF – 2 Way SSL Security using Certificates

I had to work extensively in this topic, and had to go through hundreds of blogs and articles to finally make it work. It’s actually pretty simple but for someone who is new to WCF, it might give a few sleepless nights and some terrible days.

This article assumes that you have a decent knowledge on WCF, IIS hosted WCF Services, transport security and digital certificates.

Configuring the Service:

Open your Service’s web.config file and edit it’s binding configuration as below:

 <bindings>
<wsHttpBinding>
<binding name="CertificateWithTransport">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>

The above binding configuration uses wsHttpBinding with Transport mode security. You can also notice that the clientCredentialType is mentioned as “Certificate”. It means, that the consumer of the service is authenticated using a certificate.

Your behavior section should look like this,

<serviceBehaviors>
<behavior name="BindingBehavior">
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>

       </behavior>
</serviceBehaviors>

Notice that the httpsGetEnabled=”true” attribute. It tells WCF to serve get request on the service. This is should be set to true when you want the consumers to get the wsdl themselves.

If this is set to false, no one will know about this service, unless you give them the wsdl file for consumption. Most of the enterprise services do set this attribute to false for security reasons.

Your Services section should look like this,

<services>
<service behaviorConfiguration="BindingBehavior"
name="servicename">
<endpoint binding="wsHttpBinding" contract="SSPNotificationReceiver.IReceiverService" bindingConfiguration="CertificateWithTransport">
</endpoint>
<!--<endpoint address="mex" binding="mexHttpsBinding"
name="MetadataBinding" contract="IMetadataExchange"/>-->
</service>
</services>

The above behavior configuration basically exposes an endpoint with information about the binding type, service contract type and the binding configuration. The bindingConfiguration attribute is the link between the binding settings and the endpoint, and the behaviorConfiguration attribute is the link between the behavior settings and the service settings.

The commented endpoint is for the meta data exchange. Since we are using SSL, the meta data exchange is also secure. But beware, may be this is the most important statement in the entire article. There is something very important about commenting this part at the end of the article.

Setting up IIS and creating the Certificates:

Now, publish the service on IIS using Visual Studio. The following screen shots show you how to configure the IIS SSL mappings.

The following example will show you how to create SSL Server and SSL client certificates using a Certificate Authority running on Windows Server 2003. You can also create your own certs for development through makecert.exe. There are multiple articles on the internet showing how to create certificates using the tool. Just do a Live Search and find out.

  • Set Anonymous Access on IIS for your website (another important task which you might easily miss out) and remove all other authentication modes.

image

  • On the Directory Security tab, click Server Certificate and choose “Create new Certificate”. Follow the wizard to generate the certificate request. The certificate request is by default created in “c:\certreq.txt”
  • Open the Certtificate Services Website. It is generally http://localhost/certsrv on the server which is running the certificate authority.

image

  • Click on the Request a Certificate link

image

  • On the next screen, click on advanced certificate request

image

  • Choose the second option in the above screen

image 

  • In the next screen, paste the contents of the c:\certreq.txt file in the saved request textbox as shown above.
  • After you click submit, the certificate is created and queued in the Pending Requests on the Certificate Authority.
  • Open Certificate Authority in the Windows Server 2003 machine

image

  • Issue the certificate.
  • Again, go back to the Certification Services and click on the “View Status of the pending requests” link in the home page.

image

  • Click on Download Certificate link and save the certificate to a location and name it SSLServerCert.cer

 image

With this, you have successfully created the SSL Server Certificate which can be used for Server Authentication purpose.

Follow these steps to create a Client Authentication certificate.

  • On the Certificate Services home page, click on Request a Certificate option which will take you to the page shown below.

image

  • Click on advanced certificate request option in this page.
  • In the next page, click on “Create and submit a request to CA” option
  • Choose “Client Authentication Certificate” in the Type of certificate needed drop down.
  • Give all text boxes with appropriate information in the Identifying Information section.
  • Check “Mark Keys as exportable” option

image

  • Click Submit
  • As you did for SSL Server Certificate, go to Certification Authority and Issue this certificate as well
  • Come back to the Certificate Services again and click on Install Certificate link

image

  • Your Certificate will be installed in your Personal Store as shown below

image

  • You can export this cert with private key and send it across to the client who is going to use the certificate for authenticating itself.

Configuring IIS for 2 Way SSL Authentication

  • On your website’s directory security tab, click on Server Certificate
  • Click next and choose the option as shown below

image

  • Follow the wizard and select the SSLServerCert.cer that you already saved
  • Once finished, again click Edit button in the Secure Communications Section in Directory Security tab.

image

  • Check the Require secure channel (SSL) option
  • Choose Require client certificates under Client Certificates section

Do not do the following steps if your service needs only SSL Server Authentication. To enable SSL Client authentication also, proceed with the following steps

  • Check Enable client certificate mapping option
  • Click Edit to create a 1-1 certificate mapping
  • Browse to the client certificate that you already created and give map a local user account to it. All requests that carry this certificate will run using the account that you give here
  • Now, you have completed the entire hosting part of the service. The Service that you created is secured by SSL Server as well as SSL Client authentication.

Configuring the client to use SSL

<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IReceiverService">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address=https://YourIP/ReceiverHost.svc behaviorConfiguration="credentialConfiguration"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IReceiverService"
contract="NotificationProxy.IReceiverService" name="WSHttpBinding_IReceiverService" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="credentialConfiguration">
<clientCredentials>
<clientCertificate findValue="99bbc6c9e6f4a6bd526bc8bb21f9c21f0716c23r"
storeLocation="CurrentUser"
x509FindType="FindByThumbprint" />

              </clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>

I have pretty much posted the entire client configuration here. There is nothing very different from the service configuration, but for the behavior and the endpoint address.

Now, you are all set to access the service through the client.

You can access the service using the browser too..

When you do so, the browser (IE) pops up a window showing all the certificates installed in your personal store. You need to select a the certificate that you already installed in it

image

Select the appropriate certificate to view the service screen.

image

That’s it. Your service is up and running on IIS, secured using 2 Way SSL Authentication.

Two most important things not to forget:

As I said earlier there are two things that you should do:

NEVER FORGET TO ENABLE ANONYMOUS ACCESS ON IIS.

NEVER FORGET TO COMMENT THE MEX ENDPOINT ON THE SERVICE CONFIG

These two things are the most crucial part of this entire process. WCF, for some reason that I don’t know, wants Anonymous Access to be enabled on the website. You will get this error if you don’t do so.

Exception: System.ServiceModel.ServiceActivationException: The service '/ReceiverHost.svc' cannot be activated due to an exception during compilation. The exception message is: Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.. --->

Next, if you forget to leave the mex endpoint uncommented, you might end up seeing this error on the event log of the service.

Exception: System.ServiceModel.ServiceActivationException: The service '/ReceiverHost.svc' cannot be activated due to an exception during compilation. The exception message is: The SSL settings for the service 'None' does not match those of the IIS 'Ssl, SslNegotiateCert, SslRequireCert, SslMapCert'.. –->

As you can see, this does not convey any reasonable thing to you, leave alone suggestions to fix the error. Be careful with these two settings.

Enjoy WCF !!