How-to: Create a Server Certificate for a WCF Service
One of the things I took a while to get used to when I started working with WCF were the certificates that are needed to secure Services.
Microsoft have configured WCF to be secure by default. This means that developers need to be much more imaginative in finding ways to open up gaping security holes in applications: there are several incantations you need to perform if you want to send passwords unencrypted over the wire, for example.
As a consequence however, if you do need to exchange security credentials, and are not in a situation where you can use Windows Credentials, you might find yourself needing to specify a Certificate that can be used to encrypt messages exchanged by client and server. You know you need one if you get errors like
System.InvalidOperationException: The service certificate is not provided. Specify a service certificate in ServiceCredentials.
The books I consulted (Learning WCF and Programming WCF Services ) talked a lot about creating Certificates that could be used in a test environment (using makecert and the like), but almost nothing about creating certificates for a production environment. Using Test Certificates even during development is also less than ideal: because they are not properly signed by the relevant authorities you have to configure WCF not to do the full security checks on them; apparently there are also some performance problems.
After digging around a bit, I figured out that the X.509 certificates that WCF says it needs are the same thing as the SSL certificates you can purchase from Thawte. Verisign. and co - call me stupid for taking so long, but I haven't seen this actually spelled out. This led me to discover an easier way of generating test certificates. Comodo offer a very nice service letting you create free test SSL certificates that are valid for 90 days. As far as I can tell, they don't stop you recreating the certificates at the end of that time either. Because they don't validate domain names for these test certificates, you can use this service to create certificates for machines on your intranet. Their prices for full certificates seem very reasonable, particularly if you need them only for intranet use.
Getting and setting up a certificate
In the hope that I'll save somebody else some time, these are the steps I follow to set up my WCF service with a certificate:
- Generate a Certificate Signing Request (CSR). The easiest way to do this is with IIS. Here's how if you use IIS 5.1 or 6.0 (see the bottom of this post for instructions using IIS7). Don't do this on a server that's serving up a site - it will change the IIS Certificate for the site. You can however create the certificate on one computer and export it to another.
- In IIS, right click on one of your websites (there'll only be the Default Web Site if you're doing this in Windows XP), then select Properties. Switch to the Directory Security tab.
- (If you see three options (Renew, Remove, Replace) that means you already have an SSL certificate configured. If you're sure it's safe to do so, you can select Remove to get back to the position of generating a new one. )
- Fill out the screens that follow. The most important one to get right is "Common name". Here you should put the same DNS name that you intend client computers to use when connecting to the Server. If, for example, you only intend to connect from the same machine, then it's fine to use "localhost". Use the server's name if you intend clients to connect over an intranet. For servers being accessed from elsewhere, include the full domain name, e.g. mymachine.mydomain.com.
- In the last but one step of the wizard, make sure you note down where IIS puts the Certificate Request File.
- On the Comodo website look for the "Get It Free Now" link; or one of the other options if you're
ready to splash out and buy a full certificate. Follow the link through to the Certificate request page.
- At this point you'll need to open up the Certificate Request File that IIS created, and copy-and-paste its contents into the appropriate box on the web page.
- Complete the rest of the request at the site, then wait for an email to come through with your certificate zipped up inside it.
- Get to the IIS Certificate Wizard as we did in step one.
- This time, it should give you the option to "Process the pending request"
- Follow through, and select the file that you got back from Comodo, or other CA.
- Complete the Wizard: the certificate is now available for use in IIS if you need it.
- Click the Start button, type mmc. then press enter. This will display an empty Management Console.
- Select "Certificates" from the list and click Add. When prompted in the following dialog, select to manage certificates for the Computer account on the Local Computer.
- Close and OK back to the main Console Window. The Certificates node should now be there.
- Check that a Certificate with your machine's domain name appears in the Personal\Certificates folder. localhost. you can use this Console to export the Certificate, and import it on another machine, to save having to create multiple test certificates. The same applies if you have created the certificate on a machine different to the Server that will use it. Right-click the certificate, then select All Tasks->Export to export from this machine; to Import on another machine, bring up this same console, then right click the Personal/Certificates folder and select All Tasks->Import.
- Open the Services config file. Look for the behaviour element that's used by your service. Under it, add a <serviceCredentials> node, then, inside that a <serviceCertificate> node. It should look something like this: Update the findValue attribute to include the domain name of your machine - whatever you put for the Common Name in the Certificate Signing Request. For completeness, I should mention that the value in the storeName attribute corresponds with the top level folder under the Certificates node in the Certificates Snap-in (thus the "Personal" folder becomes the "My" store). If for some reason IIS puts your certificate in a different folder, then you might need to change the value in storeName.
Generating Certificate Requests in IIS7
Kevan Brewer kindly sent me instructions for generating certificate requests in IIS7. These replace steps 1 and 3 above.
- Generate a Certificate Request.
- Click Start -> Run and type inetmgr.
- Click on the root node in IIS manager and double-click Server Certificates from the centre panel.
- In the Actions panel on the right, click on Create Certificate Request.
- Fill in the form paying particular attention to the Common Name field on the first page. On the last page, click the browse button, browse to the directory of your choice and enter a file name e.g. testcertificate. (I found that if I just typed a name into the box, it either created the file somewhere random or didn’t create it at all.)
- Get the Certificate Signed. This is the same as step 2 above.
- Import the Certificate into IIS.
- Back in IIS Manager, click on Complete Certificate Request. on the Actions panel.
- Browse to the directory to where the zipped certificate files were extracted, change the file type to *.* since, by default, it only shows files with a .cer extension. Select the file which most closely matches the name you entered for the Common Name field in step 1.4.
- Enter a suitable name for the friendly name (e.g. test certificate) and click OK.