title: HttpRequestMessage.GetClientCertificate() returns null in Web API
body: <p>I have a .NET4.5 WebAPI 2 app that uses SSL Client Certificates for some custom security related checks. </p>
  
  <p>When debugging the app, <code>request.GetClientCertificate()</code> returns <code>null</code> for any service call, no matter what I tried so far.</p>
  
  <p><strong>The Tested Code:</strong></p>
  
  <p>Basically, on my service's side, I have a method that goes something like this:</p>
  
  <pre><code>class CertificateChecker : ICertificateChecker
  {
      public bool Check(HttpRequestMessage request)
      {
          var cert = request.GetClientCertificate();
      }
  }
  </code></pre>
  
  <p>My unit tests with the client cert attached to the request using <code>request.Properties.Add(HttpPropertyKeys.ClientCertificateKey, cert)</code> pass (the cert comes out exactly as expected, validations work, and so on).</p>
  
  <p>However, when I use a test with an <code>HttpClient</code> calling the actual WebAPI app, with the break point set at the <code>request.GetClientCertificate()</code> line on service side, the same line returns null.</p>
  
  <p>Here's what I tried:</p>
  
  <p><strong>Client Certs:</strong></p>
  
  <ul>
  <li>Created a fake CA and put it into trusted CA store (tried both LocalMachine and current user).</li>
  <li>Created a Client Authentication (1.3.6.1.5.5.7.3.2) cert signed by that Fake CA and placed it into the Personal store (LocalMachine and Current User).</li>
  </ul>
  
  <p>(basically, followed <a href="https://www.piotrwalat.net/client-certificate-authentication-in-asp-net-web-api-and-windows-store-apps/" rel="nofollow">https://www.piotrwalat.net/client-certificate-authentication-in-asp-net-web-api-and-windows-store-apps/</a> and similar blogs)</p>
  
  <p>On my test that calls the service using <code>HttpClient</code>, attached the client cert in the following ways (none of which worked):</p>
  
  <ul>
  <li><p>Using <code>WebRequestHandler</code> with <code>ClientCertificateOptions</code> set to Manual and the cert added to the <code>ClientCertificates</code> collection.</p>
  
  <pre><code>using (var handler = new WebRequestHandler())
  {
       var cert = GetTestCert();
       handler.ClientCertificateOptions = ClientCertificateOption.Manual;
       handler.ClientCertificates.Add(cert);
  
       // and so on...
  }
  </code></pre></li>
  <li><p>Using the <code>HttpRequestMessage</code>, adding the cert as a property with the key set to <code>HttpPropertyKeys.ClientCertificateKey</code> (this approach works when unit testing as described above).</p>
  
  <pre><code>request.Properties.Add(HttpPropertyKeys.ClientCertificateKey, cert);
  </code></pre></li>
  </ul>
  
  <p>The <code>cert</code> variable is set to the expected <code>X509Certificate2</code> object in both cases.</p>
  
  <p><strong>Hosting:</strong></p>
  
  <ul>
  <li><p>IISExpress: Tried to run the app in IISExpress.</p>
  
  <p>Edited applicationhost.config with <code>iisClientCertificateMappingAuthentication enabled</code> set to "true" and the following access settings (neither worked):</p>
  
  <pre><code>&lt;access sslFlags="Ssl, SslNegotiateCert" /&gt;
  &lt;access sslFlags="SslNegotiateCert" /&gt;
  </code></pre></li>
  <li><p>Local IIS
  Set the web app to run in IIS on my local machine</p>
  
  <ul>
  <li>The site in IIS is configured with an HTTPS binding using a trusted certificate.</li>
  <li>Web app configured to use https protocol with IIS Client Cert mapping authentication enabled.</li>
  <li>Tried both the access option combinations (<code>Ssl, SslNegotiateCert</code> and <code>SslNegotiateCert</code>) (via configuration editor)</li>
  </ul></li>
  </ul>
  
  <p>In both cases, when accessing the web api via the https url using a web browser, I get the index view of the home controller to show without issue (so, the server side cert is trusted).</p>