IIS Client certificate not working. Returns 403 error

iisssl-certificatex509certificate

I'm trying to setup IIS 8 (Windows Server 2012) to accept client certificates for a secured WebAPI endpoint. Following this post I created a self signed certificate and a client certificate:

makecert.exe -r -n "CN=MyCompany" -pe -sv MyCompany.pvk -a sha1 -len 2048 -cy authority MyCompany.cer

makecert.exe -iv MyCompany.pvk -ic MyCompany.cer -n "CN=MY Client" -pe -sv MyClient.pvk -a sha1 -len 2048 -sky exchange MyClient.cer -eku 1.3.6.1.5.5.7.3.2

pvk2pfx.exe -pvk MyClient.pvk -spc MyClient.cer -pfx MyClient.pfx -po THE_PASSWORD

I installed the root certificate MyCompany.cer on the IIS server, then on IIS Manager/SSL Settings I selected the "Accept" radio button to allow the website accept client certificates.

On the client side a have a C# test console app that loads the client cert MyClient.pfx file and calls the WebAPI endpoint:

var certHandler = new WebRequestHandler();
certHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
certHandler.UseProxy = false;
var certificate = new X509Certificate2(File.ReadAllBytes(@"C:\MyClient.pfx"), "THE_PASSWORD");
certHandler.ClientCertificates.Add(certificate);
var client = new HttpClient(certHandler);
var result = client.GetAsync("https://MyServer/api/MyEndpoint").Result;
string resultStr = result.Content.ReadAsStringAsync().Result;
Console.WriteLine(resultStr);

I'm getting back a 403 error:

403 - Forbidden: Access is denied.
You do not have permission to view this directory or page using the credentials that you supplied.

I tried the same setup on my local IIS (Windows 7): Imported the MyCompany.cer file, setup SSL in IIS. This time everything works fine and the WebAPI endpoint can see the client certificate with no problem.

Any ideas?

— Update 1

I enabled Failed REquest Tracing on IIS and I get this:

<failedRequest url="https://myserver:443/"
           siteId="35"
           appPoolId="CertTest"
           processId="7248"
           verb="GET"
           authenticationType="NOT_AVAILABLE"               activityId="{00000000-0000-0000-B0AA-0280000000E0}"
           failureReason="STATUS_CODE"
           statusCode="403.16"
           triggerStatusCode="403.16"
           timeTaken="0"
           xmlns:freb="http://schemas.microsoft.com/win/2006/06/iis/freb"
           >

If I understand right the error is 403.16. I understand that happens when the certificate on the server is not imported into the Trusted Root Certification Authorities under Local Computer. I double checked and that's not my case.

Best Answer

Check that

  • On your IIS machine you have installed Server's cert issuer certificate to Trusted Root Certification Authorities under Local Computer
  • On your IIS machine you have installed Client's cert issuer certificate to Trusted Root Certification Authorities under Local Computer
  • On your client machine you have installed Server's cert issuer certificate to Trusted Root Certification Authorities under Windows User that runs console app
  • On your client machine you have installed Client's cert issuer certificate to Trusted Root Certification Authorities under Windows User that runs console app. Or you can make sure to include all necessary certificate's chain to pfx file
  • In code use X509Certificate2's ctor version with X509KeyStorageFlags.UserKeySet explicitly.

If it won't help,

  1. try to open url in IE (under the same Windows User Account that runs console app).
  2. open *.cer files with double click on a client machine under Windows User Account that runs console app and see what Windows says about they validity.
  3. change IIS SSL settings to ignore client certificate to see if it's all good with server certificate. Try both browser and console app.