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