HttpRequestMessage.GetClientCertificate () returns null in the Web API

I have a .NET4.5 WebAPI 2 application that uses SSL Client Certificates for some special security checks.

When debugging the application, request.GetClientCertificate() returns null for any service call, regardless of what I have tried so far.

Tested Code:

Basically, on my side of the service, I have a method that looks something like this:

 class CertificateChecker : ICertificateChecker { public bool Check(HttpRequestMessage request) { var cert = request.GetClientCertificate(); } } 

My unit tests with a client certificate attached to the request using request.Properties.Add(HttpPropertyKeys.ClientCertificateKey, cert) pass (the certificate is issued exactly as expected, validation works, etc.).

However, when I use a test with HttpClient that calls the actual WebAPI application, with a breakpoint set in the request.GetClientCertificate() on the service side, this same line returns null.

Here is what I tried:

Customer Certificates:

  • Created a fake CA and placed it in the CA's trusted store (tried both LocalMachine and the current user).
  • Created a client authentication certificate (1.3.6.1.5.5.7.3.2), signed by this Fake CA, and placed it in the Personal Store (LocalMachine and Current User).

(basically https://www.piotrwalat.net/client-certificate-authentication-in-asp-net-web-api-and-windows-store-apps/ and similar blogs)

In my test, which calls the service using HttpClient , I connected the client certificate in the following ways (none of them worked):

  • Using WebRequestHandler with ClientCertificateOptions set the value to Manual and the certificate added to the ClientCertificates collection.

     using (var handler = new WebRequestHandler()) { var cert = GetTestCert(); handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.ClientCertificates.Add(cert); // and so on... } 
  • Using HttpRequestMessage , adding cert as a property with the key set to HttpPropertyKeys.ClientCertificateKey (this approach works with unit testing, as described above).

     request.Properties.Add(HttpPropertyKeys.ClientCertificateKey, cert); 

In both cases, the cert variable is set to the expected X509Certificate2 object.

Hosting:

  • IISExpress: Tried to run the application on IISExpress.

    The edited applicationhost.config with iisClientCertificateMappingAuthentication enabled set to "true" and the following access parameters (none of them work):

     <access sslFlags="Ssl, SslNegotiateCert" /> <access sslFlags="SslNegotiateCert" /> 
  • Local IIS Install the web application to run in IIS on my local computer.

    • The site in IIS is configured with HTTPS binding using a trusted certificate.
    • The web application is configured to use the https protocol with IIS client authentication authentication enabled.
    • Tried a combination of access parameters ( Ssl, SslNegotiateCert and SslNegotiateCert ) (via the configuration editor)

In both cases, when accessing the web api via https-url using a web browser, I get the index of the home controller without problems (so the server certificate is certified).

+7
c # iis asp.net-web-api ssl-certificate iis-express
source share
1 answer

Excellent detailed information about your problem.

I am going to assume that the problem is with attaching the w / HttpClient client certificate, since you cannot view the server-side certificate in this situation. The entire configuration of the hosting certificate and server sounds good.

  • I would make sure that the variable X509Certificate2 cert that you attach is the public key that exists in your local certificate store (I'm not sure which store you store this in) (you can check using mmc.exe). Also make sure that the public key has a private key with it, since HttpClient is required to sign the requests.

  • In the code snippet, you have using (var handler = new WebRequestHandler()) to the rest of your code. Make sure you also create your HttpClient client = new HttpClient(handler) when used, or the handler will be deleted.

Otherwise, creating a handler looks good.

Good luck

+1
source

All Articles