IIS 7 and Client Certificates

January 24, 2010

We recently needed to restrict access to a small subset of our IIS-based website and decided to leverage client certificates as the second factor for our two factor authentication. I was surprised when I couldn’t find end-to-end instructions on how to do this anywhere on the Internet. The bits and  pieces I did find helped, but the overall implementation still took longer than I had anticipated. I’ll cover the steps I took in this blog post.

Some quick background first. Our ASP.NET based site running on IIS 7 makes use of standard cookie-based forms authentication. Our goal was to put in place a secondary auth mechanism that will further restrict access to a specific subdirectory with sensitive code. We settled on issuing each user permitted to access that directory their own SSL certificate so they and the IIS server can mutually authenticate. These so-called client certificates are just like the far more commonly used server certificates, except they authenticate the client to the server rather than the server to the client.

Step 1: Create a Self-Signed CA Certificate

Since we had full control over the environment in which our certificates were going to be used (i.e. on all clients and servers), we wouldn’t have benefited from having a top-tier certification authority (CA) like VeriSign or DigiCert issue our client certificates. That’s why we created our own and self-signed it.

As you may know, a CA certificate is sort of a master certificate that is ultimately trusted and that is used to sign other, lower level certificates. If a lower level certificate is signed by a CA certificate and a given computer trusts the CA that issued the CA certificate, it will implicitly trust the lower level certificate as well. The two certificates — the CA certificate and the lower level certificate — are related in what’s called a certificate chain. One simply derives from the other.

Utilizing a CA certificate for a purpose like ours is extremely useful. A server that is validating a large number of client certificates doesn’t have to individually trust each and every one (usually by installing them all in one of the trusted locations in its certificate store). All it needs to do is install the CA certificate (and only the CA certificate) and leave the rest up to the operating system and IIS.

Let’s create one. On Windows, you can use the MakeCert tool to create a wide range of certificates any way you like. The tool is part of the Microsoft Windows SDK and was located at C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\x64 on my computer.

makecert.exe -r -n “CN=My Personal CA” -pe -sv MyPersonalCA.pvk -a sha1 -len 2048 -b 01/21/2010 -e 01/21/2016 -cy authority MyPersonalCA.cer

This command will create two files, a PVK file that contains the certificate’s private key and a CER file that contains the public key. We’re also instructing MakeCert to self-sign the certificate (-r), give it a common name of My Personal CA (-n), make the private key exportable (-pe), use the SHA1 algorithm to sign the certificate (-a), generate a 2048-bit certificate (-len), make the certificate valid for about 6 years (-b and -e), and make this a CA certificate (-cy).

The MyPersonalCA.cer file will get installed on all the clients and servers that will participate in our two-factor authentication. The MyPersonalCA.pvk file must be closely guarded and will remain on the machine that creates our lower level certificates. The private key in the PVK file will sign them.

Step 2: Create a Client Certificate

Next, let’s create our first client certificate.

makecert.exe -iv MyPersonalCA.pvk -ic MyPersonalCA.cer -n “CN=John Doe” -pe -sv JohnDoe.pvk -a sha1 -len 2048 -b 01/21/2010 -e 01/21/2011 -sky exchange JohnDoe.cer -eku 1.3.6.1.5.5.7.3.2

We’re asking MakeCert to create a certificate that’s issued by our personal CA (-iv and ic), intended for John Doe (-n), valid for only a year (-b and -e), used for communication rather than signing (-sky), and intended only for purposes of Client Authentication (-eku). The -eku parameter is very important because certificates that aren’t marked with the Client Authentication purpose won’t be picked up by browsers.

On Windows, the convenient PKCS #12 certificate file (with a .PFX extension) is commonly used to transport certificates from one place to another. The format allows for storing the private key as well as the public key and makes password-protecting the private key and installing the certificate in general very easy. We’ll use another tool from the Windows SDK, PVK2PFX, to create John’s PFX file.

pvk2pfx.exe -pvk JohnDoe.pvk -spc JohnDoe.cer -pfx JohnDoe.pfx -po <new_private_key_password>

The PVK2PFX tool is pretty self-explanatory. It takes the .PVK file with the private key, the .CER file with the public key, and marries them together into a .PFX file. The tool was located at C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin on my machine.

At this point, we’ve got everything we need. We’ll send both MyPersonalCA.cer and JohnDoe.pfx to John and ask him to install the .CER file into the Trusted Root Certification Authorities folder and the .PFX file into the Personal folder of his computer’s certificate store. He can accomplish both tasks by double clicking on each file.

Step 3: Configure IIS 7 to Accept Client Certificates

Every site that looks to implement this mechanism must be exposed over HTTPS. There are a number of articles out there on how to do this already, such as this one from ScottGu.

Next, read over this article on IIS.net. The article does a great job describing what to do from this point onward. Few things to keep in mind:

  • One way to obtain the Base-64 encoded certificate for John Doe is to install John’s .PFX file, then open the Microsoft Management Console (run mmc.exe, CTRL-M, double click Certificates, Finish, OK, right click on John’s certificate under Personal/Certificates, export without a private key, and pick the Base-64 encoded X.509 (.CER) option).
  • You can get the IIS Administration Pack 1.0 from http://www.iis.net/expand/AdministrationPack.
  • Don’t forget to install MyPersonalCA.cer on the server hosting IIS7. You may need to restart IIS after adding/removing trusted root certificates, IIS may cache them.
  • We didn’t care about mapping client certificates to any Windows user accounts, so we left the password field empty and typed in the user’s name into the userName field to easily identify the row and the certificate.
  • To require client certificates for a given directory, select the directory in IIS Manager, double click SSL Settings, and select the Require radio button.

Is there a better/safer way to do this? Did something not work out quite right? Let me know in the comments section.

29 Responses to “IIS 7 and Client Certificates”

  1. […] client certificate wasn’t as easy. I finally came across a blog that had the answer: IIS 7 and Client Certificates which referenced another article: Configuring One-to-One Client Certificate […]

  2. Luke. said

    Great approach, but I followed your instructions to the letter. Still no go…getting a 403.7, for some reason it is not picking up the client certificate.

    • ondrej421 said

      Does this happen in all browser you have installed Luke? I’d also double check that the certificates in MyPersonalCA.cer and JohnDoe.pfx were properly installed by running MMC and loading the “Certificates — Current User” add-in.

  3. Thanks for the blog, easy to read and to follow. Unfortunatelly, I could not get it running, dispite flowing everything on the letter with 4 eyes (ok, we changed the names of the certificates to our needed). We are using IIS 7.5 and tracked the client calls on the TLS protocol level. Also we made sure the certificates have been installed correctly. No clue what’s wrong. Any idea how to fix it? The delivery of a project depends on it. Thanks.

  4. I’m also trying to follow these directions (and the ones here: http://blogs.iis.net/rlucero/archive/2008/05/23/iis-7-walkthrough-one-to-one-client-certificate-mapping-configuration.aspx) using IIS 7.5. And, like the previous commenters, I’m getting a 403 error in both Chrome and IE on Windows 7 when trying to access my test site. When I provide no certificate, I get a 401, so it seems that something is getting through, but is then being rejected.

    I have double checked my certs, blobs, etc, and everything seems to be in order as per the above suggestions. Has anyone had a breakthrough on this?

  5. I was able to fix my issue.

    The problem was that the CA cert that I used to sign the client certs was installed in the “Current User” Trusted Root Certificates store on the server running IIS. It needs to be installed in the “Local Computer” Trusted Root Certificates store since IIS runs as a local service account, not the current user. Unless it is installed in the “Local Computer” store, IIS will not be able to validate the client certificates and will throw back a 403 error.

    Use the MMC Certificates Snap-In “Import” function to manually install the CA cert in the “Local Machine” Trusted Root Certificates store. Just double-clicking on the CA cert in Explorer will install it in the “Current User” Trusted Root Certificates store by default, leading to the 403 issue.

    On the client machines, installing the CA cert in the “Current User” store is fine, since the browser runs as the “Current User” and thus has access to this store. It’s just the computer running IIS that needs the CA cert installed in the “Local Machine” store.

    Maybe this is the issue some others are running into…

    • Meanwhile, I got it fixed, too, but it kept us busy till just some days ago. After trying it again on newly setup machines, it worked in one case and uncovered that the CA-cert was not installed properly, even when we thought it was. Most likely, Andy’s hint would have helped to get a break through in our case. So for me all is left to say: his hint is quite valuable.

  6. […] I have acquired myself and also through the help of blogs and articles which I found most useful. Ondrej’s Blog in this case was extremely helpful for the certificate creation […]

  7. cycle said

    Fantastic article, thanks. Found this so useful after hours of trying other solutions which didn’t work. We’re using Mac OS X as a client and double-clicking the personal .pfx file installs it into keychain, from where you can right-click and select Identity Preferences to add the URL for the website. There’s also a handy Client Certificate Mapping extension for IIS 7 available from an MSDN blog if you search the web.

  8. Brian Holliday said

    Hi, Having major problems with installing certificates, specifically, Webdav doesn’t work with client certificates installed and long long delays connecting once certificates installed….

  9. Brian Holliday said

    although I have created the certs, I have issues trying to add to IIS and to the certificate stores. And when webdav is used I get windows authentication prompts

  10. Brian Holliday said

    Can client certificates be used with webdav? I am seeing errors –

  11. MaZ said

    Great Post! it summarizes in a few steps what I’ve been reading in other sites. I was able to make it work, but I had to do what Andy Sayler said (install the CA cert in the local machine Trusted Root Certificates store).
    Additionally to this, I had to create another certificate without the (-eku) parameter in order to have a .PFX file in order to import it into IIS 7 for my website. I don’t know if this last step was necessary, but it worked for me.

  12. […] I have acquired myself and also through the help of blogs and articles which I found most useful. Ondrej’s Blog in this case was extremely helpful for the certificate creation […]

  13. I have also been through a fairly awkward learning process with Client certificates on Windows and made a blog here… http://bliss-tech.blogspot.com/2012/10/client-certificate-installation-and.html which contains some other helpful links that I found during the my research.

  14. […] I have acquired myself and also through the help of blogs and articles which I found most useful. Ondrej’s Blog in this case was extremely helpful for the certificate creation […]

  15. Developer said

    Thanks a ton Ondrej, this post really helped me out, especially the -eku option and comments written by Andy Sayler.

  16. Jorge said

    Hello Ondrej, Firstly thanks a lot for this blog, together with this one http://asoftwaredeveloper.wordpress.com/2011/12/30/x-509-certificate/ was the solution to try client certificates out.

    But now I have a problem, maybe you Gurus know the answer: My Webserver is an embedded Win7 machine, with IIS7.5 on it. I did not want to install the Win SDK in there so I generated CA and certificates in another machine and then copied them to the server. I get a 401.1 error when doing this, Trying it in the PC where I generated the files works fine –

    so my question:
    Do you need to generate the files in the same machine wou will be using them?

    • In general, you don’t need the same machine – it would be actually dramatic if this would be the case, because usually you create one CA certificate for the whole company and use it on several machines.

      Are you sure you have installed the CA certificate properly on the IIS machine? Double-clicking would not be enough, because than it’s installed for the current user, not for the whole machine, and IIS would not find it.

      Use the Certificates snap-in of the MMC and install (import) the CA certificate at the local machine / Trusted certificate authorities.

      Please let us know if this advice did help you.

      • Jorge said

        Hi Andreas,

        Thanks for the response. I’m still trying, but with no luck. I installed the CA as “trusted” using the mmc so it goes to the local machine and not to the current user, but at no avail. Thing is: I’m using an embedded version of win7 on that machine and now I’m suspecting that there is something wrong there. One thing I noticed is that this version of the IIS has no “Client Certificates” icon on the inetmgr (a green-border certificate) so maybe there is something missing there…

      • You might consider to use a network analysing tool showing the exact TSL exchange between client and server. I just don’t have a a recommendation. We are using Chilkat HTTP libraries, which give a verbose error log if something goes wrong, but this would require some coding on your side.

      • Jorge said

        Hi Andreas, Thanks for the idea. It finally worked, but I don’t fully understand why. I was trying it with a new SSL website pointing to a vey simple html somewhere in the PC. Now I tried it by pointing to the wwwroot and now it works like a charm. This solves my issue, but it bugs me not understanding why it works now and not before… Anyway, thanks again for your replies and ideas!

  17. Hello Andreas, very nice article, thank you very much for this work. I’m wondering how could I use IIS client certificate to identify a unique machine ? is it possible to generate the private key that works only a one machine ?
    Thank you.

  18. wanttolearn1@ said

    Thanks for the article.
    i am missing one thing : which certificate should i configure on iis7, so the client whould have to use the certificate (in this example JohnDoe.pfx) when trying to reach the iis?

  19. Michael said

    Thanks for the wonderful article. The issue I have is requiring client certificate works only when my laptop is connecting to organization’s network using intranet. Once my laptop is not connected to the network and I access the web site on internet, I got 403.7 error even I was using the same laptop. Any insight on the issue is appreciated. Thanks.

    • HI Michael, it depends on what browser you are using. The client- certificate is stored on the Laptop in a special storage. While Firefox has its own storage, Chrome and MS Internet Explorer are using the Windows certificate storage. If your laptop stores your personal Windows profile in the corporate network, it might not be able to access the certificate if you are not connected.

  20. Thanks for your post. These succinct instructions helped solidify a bunch of bits and pieces of info I had, enabling me to create my certs properly.

  21. […] have followd this tutorial where i got a .CER and .PVK that i could use for creating client certificates with […]

Leave a reply to Jorge Cancel reply