Jeremy
Jeremy

Reputation: 46410

Custom X509CertificateValidator with configuration?

I'm setting up client certificates on my wcf service. All works great. The service requires client certs, my client test app supplies the cert and is able to make a request to one of the service end points.

No I want to implement a custom validator. I created a new class inheriting from X509CertificateValidator, and set it up in the services web config. I can put a breakpoint in the validate method and see it gets called. Awesome possum.

Now I want to be able to supply custom configuration parameters to the validator. The X509CertificateValidator has a LoadCustomConfiguration method which I can override, but it doesn't get called, I'm assuming it's because I'm not supplying any actual custom configuration anywhere - if that assumption is correct, how do I define my custom configuration parameters? Or is there some other way I should be doing this?

public class CustomValidator : System.IdentityModel.Selectors.X509CertificateValidator
{
    /// <summary>
    /// If the passed certificate is not valid according to the validation logic, this method throws a SecurityTokenValidationException. If the certificate is valid, the method returns to the caller.
    /// </summary>
    /// <param name="certificate"></param>
    public override void Validate(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
    {
        bool bValid = true;

        // Check that there is a certificate.
        if (certificate == null)
        {
            throw new ArgumentNullException("certificate", "Certificate was not supplied.");
        }

        bValid = certificate.Verify() &&
            DateTime.Now <= certificate.NotAfter &&
            DateTime.Now >= certificate.NotBefore;

        if (!bValid)
        {
            throw new System.IdentityModel.Tokens.SecurityTokenValidationException("Certificate is not valid.");
        }
    }

    public override void LoadCustomConfiguration(System.Xml.XmlNodeList nodelist)
    {
        base.LoadCustomConfiguration(nodelist);
    }
}

Configuration

<?xml version="1.0"?>
<configuration>

  <appSettings>    
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />    
  </appSettings>

  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>

  <system.serviceModel>

    <services>
      <service name="WCFTransportAuthCertificateCustomValidation.Service1"
               behaviorConfiguration="MapClientCertificates">
        <endpoint binding="basicHttpBinding"
                  bindingConfiguration="TransportCertificateAuthentication"
                  contract="WCFTransportAuthCertificateCustomValidation.IService1">
        </endpoint>
      </service>
    </services>

    <bindings>
      <basicHttpBinding>
        <binding name="TransportCertificateAuthentication">
          <security mode="Transport">
            <transport clientCredentialType="Certificate"></transport>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>    
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
            <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>

        <behavior name="MapClientCertificates">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>

          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="Custom" customCertificateValidatorType="X509CertificateValidation.CustomValidator, X509CertificateValidation"  />                
            </clientCertificate>
          </serviceCredentials>
        </behavior>

      </serviceBehaviors>
    </behaviors>

    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https"/>
    </protocolMapping>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

Upvotes: 2

Views: 2153

Answers (0)

Related Questions