title: Message security verification failed when authenticating a client to a WCF service hosted in IIS 7 by using Certificate credentials
body: <p>I have a WCF service running in IIS 7 over SSL, using basicHttpBinding. This is how the binding tag looks like, on both the client and the server:</p>
  
  <pre><code>&lt;basicHttpBinding&gt;
      &lt;binding name="BasicHttpBinding_IMyService"
               messageEncoding="Mtom"
               transferMode="Buffered"&gt;
        &lt;security mode="TransportWithMessageCredential"&gt;
          &lt;message clientCredentialType="UserName" /&gt;
          &lt;transport clientCredentialType="None" proxyCredentialType="None" realm="" /&gt;
        &lt;/security&gt;
      &lt;/binding&gt;
  &lt;/basicHttpBinding&gt;
  </code></pre>
  
  <p>On the server side, this is the behavior tag:</p>
  
  <pre><code>&lt;behaviors&gt;
    &lt;serviceBehaviors&gt;
      &lt;behavior name="myServiceBehavior"&gt;
        &lt;serviceMetadata httpGetEnabled="true"/&gt;
        &lt;serviceDebug includeExceptionDetailInFaults="true" /&gt;
      &lt;/behavior&gt;
    &lt;/serviceBehaviors&gt;
  &lt;/behaviors&gt;
  </code></pre>
  
  <p>Everything works fine. </p>
  
  <p>Now, I want to switch to Certificate credential type for authenticating the client and this is where I'm stuck.</p>
  
  <p>I did the following:</p>
  
  <ol>
  <li>Installed a root CA in Trusted Root Certification Authorities for
  both the Current user and the Local computer.</li>
  <li>Created a certificate under the above root CA and installed it in
      the Personal store for the Current User and for the Local Machine.</li>
  <li>Created a mapping between a local user on the machine running IIS
  (it's actually the same machine as with the client, which is my
  development machine) as described in <a href="http://blogs.iis.net/rlucero/archive/2008/05/23/iis-7-walkthrough-one-to-one-client-certificate-mapping-configuration.aspx" rel="nofollow">here</a></li>
  <li>The SSL flags for the IIS configuration for the website in
  system.webServer/security/access are: SslNegotiateCert (which is the
  default)</li>
  <li>Set "Accept" Client certificates in IIS for the Web Site and for my
  application (Are these settings required? From my understanding IIS
  has nothing to do with this certificate used for authenticating the
  client by WCF.)</li>
  <li>The application pool in IIS for my application runs under
  LocalService account. I granted acces to LocalService for the
  certificate installed in the Local Machine store by using the
  WinHttpCertCfg.exe tool: WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY
  -s "Jackson Michael" -a "LocalService"</li>
  </ol>
  
  <p>The binding tag for both the client and the server now look like this:</p>
  
  <pre><code>&lt;basicHttpBinding&gt;
      &lt;binding name="BasicHttpBinding_IMyService"
               messageEncoding="Mtom"
               transferMode="Buffered"&gt;
        &lt;security mode="TransportWithMessageCredential"&gt;
          &lt;message clientCredentialType="Certificate" /&gt;
          &lt;transport clientCredentialType="None" proxyCredentialType="None" realm="" /&gt;
        &lt;/security&gt;
      &lt;/binding&gt;
  &lt;/basicHttpBinding&gt;
  </code></pre>
  
  <p>For the client:</p>
  
  <pre><code>&lt;behaviors&gt;
      &lt;endpointBehaviors&gt;
          &lt;behavior name="clientCertificateEndpointBehavior"&gt;
              &lt;clientCredentials&gt;
                  &lt;clientCertificate storeName="My" storeLocation="CurrentUser" x509FindType="FindBySubjectName" findValue="Jackson Michael" /&gt;
              &lt;/clientCredentials&gt;
          &lt;/behavior&gt;
      &lt;/endpointBehaviors&gt;
  &lt;/behaviors&gt;
  </code></pre>
  
  <p>On the server side:</p>
  
  <pre><code>&lt;behaviors&gt;
    &lt;serviceBehaviors&gt;
      &lt;behavior name="myServiceBehavior"&gt;
        &lt;serviceMetadata httpGetEnabled="true"/&gt;
        &lt;serviceDebug includeExceptionDetailInFaults="true" /&gt;
          &lt;serviceCredentials&gt;
              &lt;clientCertificate&gt;
                  &lt;authentication mapClientCertificateToWindowsAccount="true" certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck" /&gt;
              &lt;/clientCertificate&gt;
          &lt;/serviceCredentials&gt;
      &lt;/behavior&gt;
  &lt;/behaviors&gt;
  </code></pre>
  
  <p>The client gets a System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.</p>
  
  <p>Looking in the trace output with the Trace Viewer I find this:</p>
  
  <blockquote>
    <p>System.IdentityModel.Tokens.SecurityTokenValidationException: The
    X.509 certificate SN=Jackson, G=Michael, OID.2.5.4.41=Jackson Michael,
    E=michaeljackson5@jacksons.com, CN=Jackson Michael, C=LK chain
    building failed. The certificate that was used has a trust chain that
    cannot be verified. Replace the certificate or change the
    certificateValidationMode. A certification chain processed correctly,
    but one of the CA certificates is not trusted by the policy provider.</p>
  </blockquote>
  
  <p>If I edit the serviceBehavior tag and set certificateValidationMode="None", I get the same result.</p>
  
  <p>The questions are:</p>
  
  <ol>
  <li>Why is certificateValidationMode="None" ignored?</li>
  <li>What am I missing to make the authentication work by using the
  default certificateValidationMode="ChainTrust" or even with
  PeerOrChainTrust?</li>
  </ol>
  
  <p>Thank you.</p>