Question

I have a WCF client/service app that relies on secure communication between two machines and I want to use use x509 certificates installed in the certificate store to identify the server and client to each other. I do this by configuring the binding as <security authenticationMode="MutualCertificate"/>. There is only client machine.

The server has a certificate issued to server.mydomain.com installed in the Local Computer/Personal store and the client has a certificate issued to client.mydomain.com installed in the same place. In addition to this the server has the client's public certificate in Local Computer/Trusted People and the client has the server's public certificate in Local Computer/Trusted People.

Finally the client has been configured to check the server's certificate. I did this using the system.servicemodel/behaviors/endpointBehaviors/clientCredentials/serviceCertificate/defaultCertificate element in the config file.

So far so good, this all works. My problem is that I want to specify in the server's config file that only clients that identify themselves with the client.mydomain.com certificate from the Trusted People certificate store are allowed to connect.

The correct information is available on the server using the ServiceSecurityContext, but I am looking for a way to specify in app.config that WCF should do this check instead of my having to check the security context from code.

Is that possible? Any hints would be appreciated.

By the way, my server's config file looks like this so far:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="MyServer.Server" behaviorConfiguration="CertificateBehavior">
        <endpoint contract="Contracts.IMyService" binding="customBinding" bindingConfiguration="SecureConfig">
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/SecureWcf"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="CertificateBehavior">
          <serviceCredentials>
            <serviceCertificate storeLocation="LocalMachine" x509FindType="FindBySubjectName" findValue="server.mydomain.com"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <customBinding>
        <binding name="SecureConfig">
          <security authenticationMode="MutualCertificate"/>
          <httpTransport/>
        </binding>
      </customBinding>
    </bindings>
  </system.serviceModel>
</configuration>
Was it helpful?

Solution

There doesn't appear to be a way to do what I want using web.config.

I ended up adding a behavior with this tag:

<clientCertificate>
  <authentication certificateValidationMode="PeerTrust" trustedStoreLocation="CurrentUser" revocationMode="NoCheck"/>
</clientCertificate>

And then add the client's certificate to the "trusted people" certificate store of the user that the server runs as.

OTHER TIPS

Check out the WCF Security Guidance page on Codeplex - excellent and very useful stuff!

In particular, check out the How-To's and even more specifically the

How To – Use Certificate Authentication and Message Security in WCF calling from Windows Forms

It explains in great detail how to set up a WCF service which requires its clients to present a valid certificate, and how to check that. If you want to allow only a single client, deploy that certificate only specifically to that one single client.

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top