WCF certificate chain trust authentication: "The caller was not authenticated by the service."

AndiDog picture AndiDog · Sep 7, 2011 · Viewed 7.2k times · Source

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?

Answer

AndiDog picture AndiDog · Sep 8, 2011

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>