Wednesday, February 8, 2012

Applying and Using a SSL Certificate With A Self-Hosted WCF Service

(Please read my 1st post on this topic called Create A Self-Signed SSL Certificate Using IIS 7 if you need to know how to create a self signed SSL certificate)
If you create enough WCF services eventually you are probably going to need to self host your WCF Service as opposed to using IIS. The most common way of doing this is probably a Windows Service which is a great environment to host WCF services as they automatically begin and end with the server and OS being up or down and are always running in the background.

However when using a Windows Service you might find it is not as straight forward to use a SSL certificate with your exposed WCF service. This is true as there is no wizard style interface for applying SSL certificates to Windows Services like IIS provides, however after following the steps outlined here you will see that it is not so bad. Overall the process is easy to repeat for multiple services and ports once you are used to doing it.

The 1st step is to configure your WCF service to use a binding and configuration that supports HTTPS and SSL. For this example, we will use a simple WCF service that uses the 'basicHttpBinding' configuration. As with any WCF configuration, remember the references to the contract Interface and implementing class are case sensitive so if you run into any errors check your spelling. The main configuration changes to allow HTTPS on the service are to change the metadata publication binding to 'mexHttpsBinding' and by setting 'httpsGetEnabled' to 'true' on the service behavior. The SSL is handled by transport-level security using certificates. The entire service configuration is below:

<!--WCF Services Defined-->
<service name="WcfServiceTest.MyWCFService"
<endpoint address=""
contract="WcfServiceTest.IMyWCFService" />
<endpoint address="mex"
contract="IMetadataExchange" />
<add baseAddress="https://DevMachine1234:8050/WCFServices/MyWCFService" />

<!--WCF Service Behavior Configurations-->
<behavior name="MyWCFServiceBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />

<!--WCF Service Binding Configurations-->
<binding name="BasicHttpSSLBinding">
<security mode="Transport" />

Notice the 'baseAddress' value I used. The most important part here is that the host name of the service must match that of the SSL certificate I bind to the port selected. In my instance the machine name is 'DevMachine1234' and so is the name of my SSL certificate. You can actually create a SSL certificate named 'localhost' if you prefer and use that instead. If this is a true production service and you make the service address, then you will need to get a SSL cert with a matching name from a provider like Verisign or GoDaddy. Test this all and have a complete understanding before spending money on SSL certificates; no use wasting money on a misunderstood process.

Also notice I selected port '8050'. This is arbitrary, but remember there are certain port restrictions, and only 1 SSL certificate can be bound to any single port. We now need to apply the SSL certificate for our service (we are using a self-signed certificate for testing purposes) to the 8050 port before we can test our service.

The 1st thing we need is the Thumbprint value from the SSL certificate. We can use IIS to look at the installed SSL cert and grab the thumbprint value. Open up IIS, and select 'Server Certificates'. Double-click on the appropriate SSL certificate and go to the details tab. Scroll to the bottom and find the 'thumbprint' value of the certificate. Copy it out from the 1st character to the last into notepad and remove all spaces. Take caution to not copy the 1st space as it will translate into a '?' (question mark) when pasted into the command window to apply the SSL certificate in a later step. Save this for the next step.

Begin by clicking on the 'Start' button in windows and type in 'CMD' in the search box but do not press enter yet. Right-click the 'cmd' program and select 'Run as administrator' as shown below. This ensures we add the SSL certificate to the port with proper rights.

We need to use the 'netsh' tool (replacement in W2K8 and Windows 7 for the old httpcfg.exe tool) to apply the SSL certificate. We need the certificate thumbprint (gathered above) and an application ID value. The easiest way to get the 'appid' value is to use the GUID in the 'AssemblyInfo' file for the WCF project as pictured below. Copy it out as well and have ready for applying to the command window in the next step.

The command to add the SSL certificate to the port we configured in our WCF service is as follows:

netsh http add sslcert ipport= certhash=3e49906c01a774c888231e5092077d3d855a6861 appid={2d6059b2-cccb-4a83-ae08-8ce209c2c5c1}

After applying the command and pressing enter you should see a message that the certificate was successfully added.

If you want, you can verify it has been added and view any SSL certificate that has been applied by entering the following command:

netsh http show sslcert

You will see the command window output in groups displaying any SSL certificates that have been applied as shown below. Notice you can see the SSL certificate 'hash' value which is the thumbprint value we used.

If you were doing this process in a production environment or on a remote server, make sure to apply the appropriate SSL certificate that has been imported and installed on the server 1st, to the port you need prior to starting the Windows Service (it actually will not work without it).

At this point we are ready to start our service on our local machine. In VS.NET I set my service (not the host in this instance) to be the startup project. I then begin debugging. You will notice the 'WCF Test Client' tool will pop-up and display all locally hosted services. This is probably were most folks will encounter some errors. Read the error description because they are typically meaningful and give direction on what to fix. Odds are it is caused by the SSL certificate not being applied to the same port configured, a mismatched name on the certificate to the service's domain name, or a mistake in configuration. Go over all steps again to make sure everything is correct. As you can see below our WCF service exposed via a HTTPS endpoint is up and running.

The last step to verify everything is working properly is to copy the address of the locally hosted service and consume it in another test application.

Add the copied address as a service reference to the project and make sure you do not receive any exceptions.

The successfully added service will be shown in Solution Explorer with the name you provided.

My recommendation is to get all of this working as I did in a local test environment 1st and understand all of the pieces. For those totally new to WCF it can be a lot to digest and fixing problems can take time and a deeper understanding of WCF so be patient.

For more information on the other commands available to the netsh.exe command line tool (like removing SSL certificates from a port), please see the following reference:


Post a Comment