How do I implement Client Certificate authentication the right way?

13,100

In your scenario, you don't need to configure certificates in WCF, IIS handles those for you. You can clear the entire <serviceCredentials> block, because:

The <serviceCertificate> of <serviceCredentials> specifies an X.509 certificate that will be used to authenticate the service to clients using Message security mode, which you do not use, and the <clientCertificate> of <serviceCredentials> defines an X.509 certificate used to sign and encrypt messages to a client form a service in a duplex communication pattern.

See here how to map client certificates to user accounts.

Share:
13,100
Guillaume Schuermans
Author by

Guillaume Schuermans

Updated on June 08, 2022

Comments

  • Guillaume Schuermans
    Guillaume Schuermans almost 2 years

    WCF is extremely extensible and has a lot of ready-to-use features, however I continue struggling with some topics and the more documentation I read, the more I get confused.

    I hope to get some answers from the community. Feedback on any assumption or question is extremely welcome.

    For the record: to really accept a single answer I should divide this post in multiple questions but it would lead to even more confusion. I am pretty sure there are some real WCF experts online who can answer the few questions in this document all at once so I can accept a single answer as the real deal to setup clientcertificate authentication using IIS the right way.

    Let me sketch the situation and partner request:

    1: The partner requirement and the question to use a client certificate.

    Partner X needs to call an API on my backend and they have the clear requirement to use Clientcertificate authentication. They created the clientcertificate and provided us the certificate with only the public key since it seems only logic they keep the private key actually private and in their own system(s). The certificate was imported on the local computer account and looking at the certification path this is valid. All intermediate certification authorities and in the end the root certification authority are trusted.

    2: Our WCF serverside configuration

    I have a serviceBehavior configured as such:

    <behavior name="ClientCertificateBehavior">
        <serviceMetadata httpsGetEnabled="true" />
            <serviceCredentials>
            <serviceCertificate findValue="<serialnumber here>" x509FindType="FindBySerialNumber" />
            <clientCertificate>
              <authentication certificateValidationMode="PeerTrust" />
            </clientCertificate>
        </serviceCredentials>
    </behavior>
    

    I guess I made a first mistake here and should use ChainTrust to actually validate the certificate using its certification path. What do you think?

    The service is configured as such:

    <service behaviorConfiguration="ClientCertificateBehavior" name="<Full service namespace and servicename>">
        <endpoint binding="basicHttpBinding" bindingConfiguration="Soap11CertificateBasicHttpBinding"
            contract="<The interface>"></endpoint>
    </service>
    

    The binding looks like this:

    It is a basicHttpBinding to force SOAP1.1 (according to the partner's specifications).

    <binding name="Soap11CertificateBasicHttpBinding">
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
    </binding>
    

    3: Hosting the WCF service in IIS and the IIS configuration

    We host our WCF services in IIS7. We configured the folder in which the services reside to require SSL and to accept Client certificates. Authentication-wise anonymous authentication is enabled.


    The thing is that communication from the partner works and we were confident that everything was OK, however toggling the IIS-setting to 'require' client certificate shows us that all of a sudden it is no longer possible to successfully call our service.

    Am I correct to assume that following things are not done correctly:

    • The serviceCerticate in the serviceBehavior is not really necessary. This is a setting used by the client. Or is it necessary to provide this certificate information for the service endpoint to match the certificate that's being send by the client?

    • For clientcertificate authentication to really work in IIS the certificate needs to be mapped to a user. This user should be granted permissions on the folder containing the services and all authentication mechanisms (anonymous, windows,...) should be disabled. This way IIS will handle the actual handshake and validate the servicecommunication. Or is it more a matter of extra security mapping the certificate to a user?

      • By setting 'Accept' on IIS we bypass the actual certificate validation between client and server.

      • All authentication mechanisms like 'anonymous' and 'windows' have to be disabled on IIS for the folder which holds the services.