Introduction
This article provides a step-by-step guide to securing WCF services with certificates. Most articles of this nature use makecert.exe to generate sample certificates. This is great for testing purposes, but what if you want to use certificates that are issued from a Certificate Authority (CA)? This article will show you how to generate certificates with Microsoft Certificate Services and use them to secure your WCF services.
Prerequisites
This article assumes that you know how to create and consume a WCF service.
You should have two separate machines to follow the steps in this article:
- Client machine — this can be your development system. You should have the .NET Framework 3.0 or higher installed.
- Server machine — this will function as our WCF server as well as a Certificate Authority. (Note that you may want to have a separate server function as the CA.) You should have Windows Server 2003 with the .NET Framework 3.0 or higher installed. If you do not have a separate machine, it is recommended that you create a virtual machine with these specifications. This can be achieved by using Virtual PC 2007.
Section 1: Install Microsoft Certificate Services on the Server
You have two options for obtaining X.509 certificates for which to secure your services:
- Purchase a certificate from a trusted certificate authority such as VeriSign, Thawte, RapidSSL, etc.
- Create your own certificate authority
This article focuses on the 2nd option by creating certificates using Microsoft Certificate Services. To install Microsoft Certificate Services, follow these instructions:
- On the server machine, go to Control Panel > Add or Remove Programs
- Select Add / Remove Windows Components
- Check Certificate Services and click Next to complete the installation.
- Select Stand-alone root CA and click Next
- Fill out the CA Identifying Information
- Complete the installation by accepting the remaining defaults
Section 2: Configure the client to trust the new certificate authority
Windows is preconfigured with a set of trusted certificate authorities. Of course, our new certificate authority isn't in this list. Follow these steps to allow your client machine to trust the new certificate authority.
- On the client machine, open a web browser and go to http://<server name>/certsrv. This will bring up a page similar to the following:
- Click Download a CA certificate, certificate chain, or CRL
- Click Download CA certificate chain. Save the certnew.p7b file to your file system.
- Load the Certificates MMC Snap-In. Note that several steps in this article will require loading this snap-in. The following instructions show how to do this, and they will not be repeated in subsequent sections.
- Select Start > Run and type "mmc" to open the Microsoft Management Console
- Select File > Add / Remove Snap-in
- Click the Add button
- Select Certificates and click the Add button
- Select Computer Account and click the Next button
- Click the Finish button
- Click the Close and OK buttons
- Expand Certificates (Local Computer) > Trusted Root Certification Authorities > Certificates
- Right-click the Certificates folder and select All Tasks > Import
- Click Next, then click Browse
- Select PKCS #7 Certificates from the Files of type drop down list
- Browse to the certnew.p7b file that you saved in step 3. Click the Open button
- Click Next, Next, and Finish. You should now see your CA listed as a Trusted Root Certificate Authority.
Note: If your WCF server is different than your CA server, you will need to repeat Section 2 for the WCF server machine.
Section 3: Create a Client Certificate
This section explains how to create a certificate for our WCF client.
- On the client machine, open a web browser and go to http://<server name>/certsrv
- Click Request a certificate
- Click advanced certificate request
- Click Create and submit a request to this CA
- Fill out the form as shown in the image below:
- Click Submit and accept the warning message. You will see a confirmation that your request has been received and is pending.
- On the server, select Start > Programs > Administrative Tools > Certification Authority
- Expand the CA and click Pending Requests. You should see your client certificate request in the list.
- Right-click the request, select All Tasks > Issue to approve the certificate
- On the client machine, go back to http://<server name>/certsrv
- Click View the status of a pending certificate request
- Click the Client Authentication Certificate link and accept the warning message.
- Click Install this certificate and accept the warning message.
At this point, the certificate's public and private key are now installed on the client machine. The next step is to install the certificate's public key on the server.
- Load the Certificates MMC Snap-In on the client machine. Follow these instructions to load the snap-in.
- Expand Certificates (Local Computer) > Personal and click Certificates
- Right-click the client certificate and select All Tasks > Export
- In the Certificate Export Wizard, click Next, Next, Next, select a file name, Next, and Finish
- Copy the exported certificate file to the server
- Load the Certificates MMC Snap-In on the server machine. Follow these instructions to load the snap-in.
- Expand Certificates (Local Computer) > Personal.
- Right-click Certificates, select All Tasks > Import
- In the Certificate Import Wizard, click Next, select the file that you exported in step 17, click Next, Next, and Finish. The client's public key should now be installed on the server.
Section 4: Create a server certificate
Creating a server certificate is very similar to creating a client certificate, so this section doesn't contain as many screenshots as Section 3.
- On the server machine, open a web browser and go to http://<server name>/certsrv
- Click Request a certificate
- Click advanced certificate request
- Click Create and submit a request to this CA
- Fill out the form as shown in the image below:
- Click Submit and accept the warning message. You will see a confirmation that your request has been received and is pending.
- On the server, select Start > Programs > Administrative Tools > Certification Authority
- Expand the CA and click Pending Requests. You should see your client certificate request in the list.
- Right-click the request, select All Tasks > Issue to approve the certificate
- Go back to http://<server name>/certsrv
- Click View the status of a pending certificate request
- Click the Server Authentication Certificate link and accept the warning message.
- Click Install this certificate and accept the warning message.
- Now, if you try to load your service in a browser, you would likely get an error similar to the following:
System.Security.Cryptography.CryptographicException: Keyset does not exist
ArgumentException: The certificate 'CN=My Server Machine' must have a private key that is capable of key exchange. The process must have access rights for the private key.
To fix this problem, we need to give the ASPNET or NETWORK SERVICE account permission to read the certificate. This can be achieved with the following tool:
Windows HTTP Services Certificate Configuration Tool
Once this tool is downloaded, execute one of the following commands (depending on your server configuration).
C:\Program Files\Windows Resource Kits\Tools>winhttpcertcfg -g -c
LOCAL_MACHINE\My -s "My Server Machine" -a ASPNET
C:\Program Files\Windows Resource Kits\Tools>winhttpcertcfg -g -c
LOCAL_MACHINE\My -s "My Server Machine" -a "NETWORK SERVICE"
At this point, the certificate's public and private key are now installed on the server machine. The next step is to install the certificate's public key on the client.
- Load the Certificates MMC Snap-In on the server machine. Follow these instructions to load the snap-in.
- Expand Certificates (Local Computer) > Personal and click Certificates
- Right-click the server certificate and select All Tasks > Export
- In the Certificate Export Wizard, click Next, Next, Next, select a file name, Next, and Finish
- Copy the exported certificate file to the client
- Load the Certificates MMC Snap-In on the client machine. Follow these instructions to load the snap-in.
- Expand Certificates (Local Computer) > Personal.
- Right-click Certificates, select All Tasks > Import
- In the Certificate Import Wizard, click Next, select the file that you exported in step 17, click Next, Next, and Finish. The server's public key should now be installed on the client.
Section 5: Certificate Review
We have now accomplished the following:
- Created a Certificate Authority on the server machine
- Trusted the Certificate Authority on the clinet machine
- Created a client certificate on the client machine
- Installed the client certificate's public key on the server machine
- Created a server certificate on the server machine
- Installed the server certificate's public key on the client machine
Section 6: WCF Service Configuration Changes
The following is the WCF service's web.config file:
- Message security via certificates has been enabled on the custom binding.
- The client certificate requirements have been defined on the custom behavior. The ChainTrust value specifies that the certificate chain must be validated. The
revocationMode
is set to NoCheck. It is recommended that this value be set to Online in a production environment so that revoked certificates are not allowed. This requires that you have a properly configured revocation server. This is outside of the scope of this article, but the following page will point you in the right direction:
Specify certificate revocation list distribution points in issued certificates
- The Location of the server certificate has been specified on the custom behavior. Note that you may want to use a more specific search method than
FindBySubjectName
since you may have multiple certificates with the same subject. FindByThumbprint
should be sufficient for locating a unique certificate.
Section 7: WCF Client Configuration Changes
The following is the WCF client's app.config file:
- The client is communicating with a server called myserver, but the server is identifying itself as My Server Machine (as defined in the certificate). As a workaround, we have set the dns value to My Server Machine. This is not necessary if the certificate matches the host name.
- The Location of the client certificate has been specified on the custom behavior.
- The server certificate authentication options have been defined on the custom behavior.
- Message security via certificates has been enabled on the custom binding.
Your client should now be able to securely communicate with the service.
Conclusion
As you can see, using WCF with certificates can be a tedious process, but there are certain scenarios that warrant this level of security. I hope this article helps you avoid some of the common pitfalls associated with this security solution.