0
votes

I'm trying to help troubleshoot a third-party self-hosted web service written in WCF that requires mutual authentication. The issue is that web service is returning a 401 Unauthorized. I've read several articles about how to write the client and server pieces in WCF to use mutual authentication, but I still have the following questions:

  1. Once the client sends the client certificate, how does the WCF service determine whether or not to accept it as being an authenticated endpoint with access to the given resource. Does the certificate only need to be trusted by the service being able to find the certificate's root CA in the certificate store as a trusted root CA, or is there some mechanism that maps the certificate to a list of entities that have been identified as allowed to access the resource?

  2. Normally when I've seen mutual authentication used, in Wireshark I see the server respond to a Client Hello and Certificate Request with a Server Hello, Certificate, and Certificate Request. However, in the case I am troubleshooting, I do not see the server send a Certificate Request. I believe the client is sending its certificate in encrypted data, but I'm not able to decrypt the data to see it. Is there a way to force the WCF service to send a Certificate Request with the Server Hello?

The configuration file has the following:

<bindings>
  <webHttpBinding>
    <binding name="webHttpTransportSecurity">
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
    </binding>
  </webHttpBinding>
</bindings> 

I believe that's enough to indicate the client should authenticate with a certificate, but now how the service decides if that certificate is one that's allowed?

1
Do you already have your "cert auth settings" configured in your web config (wcf definition section)? - tgolisch
That's the part I'm not entirely understanding. The configuration file has the following: <bindings> <webHttpBinding> <binding name="webHttpTransportSecurity"> <security mode="Transport"> <transport clientCredentialType="Certificate" /> </security> </binding> </webHttpBinding> </bindings> I believe that's enough to indicate the client should authenticate with a certificate, but now how the service decides if that certificate is one that's allowed. - Troy Tricker

1 Answers

0
votes

Your binding definition looks correct. The certificate is defined in the endpointBehaviors. It is a little hard to follow, because it is split-up in separate XML groups.

Here is an example of what is working for my projects:

<client>
  <endpoint address="(address to our)WebService.svc"
            behaviorConfiguration="behaviorConfig"
            binding="webHttpTransportSecurity"
            bindingConfiguration="bindingConfig"
            contract="((your contract name))"
            name="mainEndPoint">
    <identity>
      <certificateReference findValue="CN=((cert name like blah.blah.blah-blah.blah)), OU=((lookup)), O=((lookup))"
                            storeLocation="LocalMachine"
                            storeName="TrustedPeople"
                            x509FindType="FindBySubjectDistinguishedName" />
    </identity>
  </endpoint>
</client>
<bindings>
  <!-- you already have a good looking binding (above) -->
</bindings>
<behaviors>
  <serviceBehaviors ...etc  />
  <endpointBehaviors>
    <behavior name="behaviorConfig">
      <clientCredentials>
        <clientCertificate findValue="CN=((short name)), OU=((lookup)), O=((lookup))"
                           storeLocation="LocalMachine"
                           storeName="My"
                           x509FindType="FindBySubjectDistinguishedName" />
        <serviceCertificate>
          <defaultCertificate findValue="CN=((same content from certificateReference above)), OU=((lookup)), O=((lookup))"
                              storeLocation="LocalMachine"
                              storeName="TrustedPeople"
                              x509FindType="FindBySubjectDistinguishedName" />
          <authentication certificateValidationMode="PeerTrust"
                          revocationMode="NoCheck"
                          trustedStoreLocation="LocalMachine" />
        </serviceCertificate>
      </clientCredentials>
      <callbackTimeouts />
    </behavior>
  </endpointBehaviors>
</behaviors>