Separate certificates for Transport and Message security in WCF

I’ve recently had to solve a rather difficult problem involving web service security using Microsoft’s WCF framework. This particular problem is the inability to use separate x509 client-side certificates when combining Message signing + transport (SSL) security using standard WCF functionality.

Before I start writing about it using my own words, I have to mention that I did not solve anything myself, but rather was immensely helped by this little gem right here: That article provides a workable, simple and elegant workaround to an annoying limitation of the WCF framework and because it is kind of alone and lost out there, I wanted to take the time to rewrite my own version of it in an effort to provide an extra copy and increase the web visibility of this knowledge.

What are we dealing with?

WCF is a great framework, but like most frameworks it has limitations. One of those limitations is that the framework does not provide a way to specify and use two different client-side certificates when combining Message level security (SOAP message signing) and Transport level security (SSL with client authentication).
Although maybe a little uncommon, this is a real world situation that I’ve personally had to deal with very recently in an effort to improve security between two finance-related applications. One might argue that it may be a little too much security, but in this case it wasn’t the developer’s call – and I would expect it to be the same way in any other financial institution.

In WCF, using a certificate for a specific service endpoint is normally done through the use of a Behavior extension. In this case, the framework provides the clientCredentials extension which exposes a clientCertificate element to be configured. The following example shows a standard clientCredentials configuration:

As we can see, there is only one clientCertificate element exposed and the framework does not provide a way of specifying another of these elements. Also, WCF won’t allow us to get around this limitation by combining two clientCredentials behaviors on the same endpoint (combining several behaviors is doable programmatically, but the framework will not allow combining two behaviors that share the same base class).
So we’re kind of stuck here, and the only way to get around this limitation is to extend the framework.

How do we fix this? [Tutorial]

The solution is to create our own behavior extension that will support the addition of another certificate. Because behavior extensions are provided as extensibility points by the WCF framework, there will be very little integration work involved – which is a good thing!

Creating the new classes

To make things easier, we don’t need to create a new behavior from scratch – we just extend the existing System.ServiceModel.Description.ClientCredentials class. Our new DualCertificateClientCredentials class will simply add support for finding and storing a second certificate through the TransportCertificate property, while conserving the existing ClientCertificate property which will be used for message security, as shown in the code below:

You’ll notice that the CreateSecurityTokenManager method has been overridden and uses another custom class called DualCertificateSecurityTokenManager. This method is used by WCF to issue the right security tokens for the request depending on the security settings that are configured for the endpoint. Once again, instead of creating a class from scratch, we just extend the System.ServiceModel.Security.Tokens.ClientCredentialsSecurityTokenManager class, as shown in the code below:

The token manager is where the magic happens. The overridden CreateSecurityTokenProvider method takes care of checking the security requirements passed on by the framework and selecting the right certificate depending on the context (Message or Transport). In a Transport + Message security context, this method will be called twice (one for each security requirement).

Now all that is left to do is to provide support for declarative configuration for our new behavior extension – because we still want to use the web.config file to set everything up. Once again, we just need to extend the System.ServiceModel.Configuration.ClientCredentialsElement class, as shown in the code below:

And that’s all the custom code we need. The last step is to configure the application to actually use the new

Configuring our WCF application

The first thing you need to is make sure you are using a customBinding for your endpoints that will be making use of this new dual certificate behavior. Why? Because it seems that when using other types of “ready to use” bindings such as basicHttpBinding or wsHttpBinding, it appears that the framework does not need to create more than one security Token provider. This means that there is only a single call to the overridden CreateSecurityTokenProvider method, which prevents our second certificate from being used.

Note: I haven’t done extensive testing on this part nor did I spend time trying to get this to work with these other types of bindings, so I might very well be proven wrong on this point. If anybody gets this to work with basic or WS binding, please let me know in the comments!

Anyway, your binding should roughly look like the below code, with small variations in the configuration depending on your environment:

The next thing to do is register and configure our new behavior extension, as shown in the below code (replace values as needed for your environment, such as assembly, namespace and certificate find values):

Finally, configure your endpoint(s) to make use of the custom binding and, more importantly, our custom behavior extension, as shown in the example below:

Please note that:

  • The bindingConfiguration property corresponds to the [name] given to the custom binding
  • The behaviorConfiguration property corresponds to the [name] used to register the behavior extension

That’s all for today. Hopefully this will be as useful to others as it was to me!

Disclaimer note: this article is an improved rewrite of a 2009 post from blogesh that can still be found at the following address:
Credit for this work goes to blogesh, so make sure you drop by his blog to thank him if you’ve found this useful!

This entry was posted in Work and tagged , , . Bookmark the permalink.

One Response to Separate certificates for Transport and Message security in WCF

  1. Wiktor says:

    Your article helped me solve problem, with I was struggling for almost two weeks! You can extend it by configuration needed to work with two different certificates from service (transport and message). All you need is section with specified , this certificate will be used for verifying signatures from replies. Last thing is section in endpoint configuration (in case that service certificates used for transport and message layer have different CN). Identity dns value should be equal to CN of certificate used for verifying service signatures.

Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>