Avoiding X.509 chain policy caching when using WCF with certificate security

A while ago my customer came to me with an issue that was a bit tricky to find a solution to.

Their system uses a Windows forms client and a WCF service running on IIS7 on a Windows 2008 R2 server. The users are provided with personal certificates stored on smart cards. Those certificates are then used to authenticate the users with the WCF service using their AD accounts.

The issue my customer was facing was:
1. New employees could not log on to the system until the application pool of the web site running the WCF service was recycled.
2. Employees who got their certificates revokeed COULD log on to the system the application pool of the web site running the WCF service was recycled.

Obviously a (totally unwanted) certificate cache of some sort was causing this behavior, so after digging around a bit I found out that System.IdentityModel was caching the X.509 chain policy in memory.

The relevant web.config settings for the WCF service looked like this:

	<authentication mapClientCertificateToWindowsAccount="true" certificateValidationMode="ChainTrust" revocationMode="Online"/>

To solve this issue I decided to implement a custom X.509 validator that builds a X509Chain manually to prevent the policy from being cached.

I changed the above web.config lines to

	<authentication mapClientCertificateToWindowsAccount="true" certificateValidationMode="Custom" customCertificateValidatorType="My.IdentityModel.MyX509Validator, My.IdentityModel" />

and implemented the custom validator like this:

using System;
using System.IO;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace My.IdentityModel
    /// <summary>
    /// Custom x509 certificate validator
    /// Richard Ginzburg - richard@ginzburgconsulting.com
    /// </summary>
    public class MyX509Validator : X509CertificateValidator
        public override void Validate(X509Certificate2 certificate)
            if (certificate == null)
                throw new ArgumentNullException("certificate", "Certificate validation failed, no certificate provided");

            X509ChainPolicy myChainPolicy = new X509ChainPolicy
                                                    RevocationMode = X509RevocationMode.Online,
                                                    RevocationFlag = X509RevocationFlag.EntireChain,
                                                    VerificationFlags = X509VerificationFlags.NoFlag,
                                                    UrlRetrievalTimeout = new TimeSpan(0, 0, 10),
                                                    VerificationTime = DateTime.Now
            X509Chain chain = new X509Chain(true) {ChainPolicy = myChainPolicy};

                bool ok = chain.Build(certificate);
                    foreach (var status in chain.ChainStatus)
                        Logging.Log("MyX509Validator: Validation failed - " + status.StatusInformation);
                    throw new SecurityTokenValidationException("Certificate validation failed when building chain");
            catch (CryptographicException e)
                throw new SecurityTokenValidationException("Certificate validation failed when building chain, " + e);

This resolved the issue, now the changes in certificate validity take effect immediately.

Some documentation on certificate validity checking can be found here: http://technet.microsoft.com/en-us/library/bb457027.aspx .

NULL values in SOAP requests

Question: how to pass a NULL value in a SOAP envelope?
Answer: Use the xsi:nil=”true” attribute on the element, and don’t forget the xsi namespace in the envelope.

Example SOAP request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <PassNullHere xsi:nil="true" />