6
votes

I would like to use certificate-based encryption and verification when communicating with a WCF service. So I created test certificates, "TempCA" as my root CA and "SignedByCA" as a client certificate signed by that CA.

When I put the client certificate in "Local Computer\Trusted People" and use certificateValidationMode="PeerTrust", the service recognizes the client and everything works as expected. But with trust chain verification (certificateValidationMode="ChainTrust"), I run into the error "The caller was not authenticated by the service".

Relevant server-side config:

<behaviors>
      <serviceBehaviors>
        <behavior name="customServiceBehavior">
            [...]
            <serviceCredentials>
                <clientCertificate>
                    <authentication certificateValidationMode="ChainTrust" trustedStoreLocation="LocalMachine" mapClientCertificateToWindowsAccount="false"  />
                </clientCertificate>
                <serviceCertificate findValue="TempCA"
                                    storeLocation="LocalMachine"
                                    storeName="My"
                                    x509FindType="FindBySubjectName" />
            </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
        <wsHttpBinding>
            <binding name="soapBindingConfiguration">
                <security mode="Message">
                    <message clientCredentialType="Certificate" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>

Relevant client config (rest auto-created by "Add Service Reference"):

<endpointBehaviors>
    <behavior name="customClientBehavior">
        <clientCredentials>
            <clientCertificate findValue="SignedByCA" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
        </clientCredentials>
    </behavior>
</endpointBehaviors>

Both client and server certificates are stored with their private key in "Local Computer\Personal" (because I'm testing on one computer), and the "TempCA" (my root certificate) is also in "Local Computer\Trusted Root Certificate Authorities".

What am I missing here? Any working examples?

2

2 Answers

5
votes

I finally found out what the problem is. Revocation checking had to be disabled. My test CA obviously doesn't have a CRL associated, so in that case WCF seems to block every client because it cannot be validated.

<clientCertificate>
    <authentication certificateValidationMode="ChainTrust"
                    revocationMode="NoCheck" ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←
                    [...]  />
</clientCertificate>
0
votes

It seems like what you are doing should work based on this MSDN article on using certificates with WCF. You may want to remove the certificate from the Personal store when using the trusted root certificate approach.

If that doesn't work either then it may be that deploying the root certificate also requires applying a group policy to your machine. Look at the "If you not using a Microsoft Enterprise root certification authority and want only groups of computers" section of this TechNet article. It says that computers may not automatically trust a root certificate if a group policy isn't applied. The two article seem to contradict each other so I'm not sure which will work.