Use a custom X509CertificateValidator with an IIS hosted WCF service and self-signed client certificate
This article describes how to use a custom X509CertificateValidator
with a Microsoft Internet Information Services (IIS) hosted Windows Communication Foundation (WCF) service and self-signed client certificate.
Original product version: Windows Communication Foundation
Original KB number: 2480671
Summary
You configure a WCF service to use a client certificate for Secure Sockets Layer (SSL) authentication. You want to use a custom X509CertificateValidator to validate the client certificates in the application-layer (WCF service), not on the Operating System (OS) layer.
WCF 3.5 SP1 doesn't allow usage of custom X509CertificateValidators
without installing a hotfix at all. In .NET 4 Windows Communication Foundation, a custom X509CertificateValidator
can be used only when the certificate could be validated successfully in the OS layer - especially it wouldn't be possible to use self-signed client certificates without installing them in the Trusted Root Certification Authorities certificate store (can be thousands of different certificates).
How to do
To enable this scenario, the following steps are necessary:
Set registry key
SendTrustedIssuerList
to 0 (DWORD) in registry. See TLS/SSL Tools and Settings for some more details.By default SChannel (the OS component used to establish SSL connections) is sending a list of trusted issuers to the client during the SSL handshake. It's done to allow the application on the client side to make it easier for the user to choose which certificate should be used. By default SChannel is sending a list of all certificates (actually the thumbprints) installed in the Trusted Certification Authorities certificate store. You could reduce this list by specifying a TCL (trusted certificate list). For example, to require clients to use their Smart Card certificates you would create a certificate trust list (CTL) which only contains the root certificate for the Certificate Authority (CA) issuing these smart card certificates. For more information about how to create a CTL, see Security in Microsoft IIS.
If you want to allow usage of client certificates, which you can't validate in the server OS (for example self-signed and not installed in Trusted Root Certification Authorities store), you need to set the value for
SendTrustedIssuerList
inHKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL
to 0. In this case, the server doesn't send a list of trusted issuers to the client and the client will allow the user to use any available client certificate.Warning
The
SendTrustedIssuerList
is a machine-wide key. When changing it all applications (Virtual Directories) using client certificate authentication are affected.This step is only necessary when it isn't possible to also validate the client certificate in the OS layer.
Override
OnGlobalPreBeginRequest
event in the HyperText Transfer Protocol (HTTP) module used by IIS (only necessary when the WCF service is hosted in IIS).Only after doing the modifications described in step 1, the client is actually sending a certificate. Before you applied this change, you would see error messages that the client didn't send a certificate (even when you set a certificate on
System.Net.HttpWebRequest
or in Internet Explorer). When the request arrives at the server side, the SChannel component is always doing a certificate validation when establishing the SSL connection. The return code of this certificate validation is passed up the stack to the callers. When your WCF service is hosted in IIS, IIS is checking the return code of the SChannel certificate validation and is terminating the request with error code 403 (Access Denied) in an early stage of the HTTP pipeline. The only way to avoid this behavior in IIS at the moment is to override theOnGlobalPreBeginRequest
event in the HTTP pipeline. It's one of the few extension points in IIS, which can only be used with native code - no managed (.NET) code. The documentation forOnGlobalPreBeginRequest
can be found on CGlobalModule::OnGlobalPreBeginRequest Method.This step is only necessary when it isn't possible to also validate the client certificate in the OS layer.
Install WCF QFE to specify custom
X509CertificateValidator
.WCF originally used the SChannel result code to validate client certificates, too. If the return code was 0 (successful), authentication was allowed and a hard-coded X509CertificateValidator was used with validation mode set to
X509CertificateValidationMode.None
(X509CertificateValidationMode Enum). Which means it wasn't possible to use any other WCFX509CertificateValidationMode
likePeer
,Chain
, orCustom
for client certificates when using security mode Transport.In .NET 4, this issue was fixed and the fix was also backported .NET 3.5 SP1. After applying the hotfix mentioned below, you're able to override the validation behavior only when specifying
X509CertificateValidationMode.Custom
. If you want to use something likeX509CertificateValidationMode.PeerTrust
orPeerOrChainTrust
, you will need to create a custom, which is reusing the default validator for the targeted validation mode. This limitation is applied to avoid breaking changes. The configuration for a customX509CertificateValidator
would look like:<serviceCredentials> <clientCertificate> <authentication certificateValidationMode="Custom" customCertificateValidatorType="Samples.MyCertificateValidator, Samples" /> </clientCertificate> </serviceCredentials>
This step is only necessary when using .NET Framework 3.5 SP1 (not for .NET 4).
Feedback
https://aka.ms/ContentUserFeedback.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see:Submit and view feedback for