Testing with client certificate authentication in a development environment on IIS 8.5

I wanted to get client certificate authentication working on a development environment. The environment in this case is a Windows 8.1 laptop so that implies IIS 8.5. It involves a significant number of steps so this will be a long post.

Configure IIS

First of all, you need to configure IIS to allow client certificate mapping authentication. As you can see in the screenshot below, there are two types of these. We need the IIS Client Certificate Mapping Authentication feature. The Client Certificate Mapping Authentication feature is used for client certificate authentication using Active Directory.

Windows Features

Generate certificates

Next step is to generate certificates. Client certificate authentication requires that your website has an HTTPS binding so we first need a certificate for the server. To obtain this, we use a self-signed certificate that we add to the trusted root certificates store of the local computer and we derive both the client and the server certificate from this root certificate.

Self-signed root certificate

To generate the root certificate, use the following command line:

makecert -r -pe -n "CN=WebSSLTestRoot"
         -b 12/22/2013 -e 12/23/2014
         -ss root -sr localmachine -len 2048

The makecert command has a lot of options, some of which we use here:

-r Generate a self-signed certificate.
-pe Allow the private key to be included in the certificate. We need this because we want to use the certificate to issue other certificates that are signed by this private key.
-n "name" Certificate subject name.
-b Validity start date.
-e Validity end date.
-ss Name of the certificate store that stores the certificate. Since we want to automatically trust this certificate, we store it with the trusted root certificates. You can find some more info on store locations here.
-sr Certificate store location where the certificate will be stored (either currentuser or localmachine).
-len Key length.

The result is a trusted root certificate as you can see in the screenshot below.

Self-signed root certificate

Server certificate

We derive the IIS server certificate from the root certificate we just generated with the following command:

makecert -pe -n "CN=www.sslclientauth.local" -b 12/22/2013 -e 12/23/2014
         -eku 1.3.6.1.5.5.7.3.1 -is root -ir localmachine -in WebSSLTestRoot
         -len 2048 -ss WebHosting -sr localmachine

This is no longer a self-signed certificate since we derive it from our own root certificate so the -r option is gone. Note that we use the subject name www.sslclientauth.local. This will become the url for the web site. Besides, we now store the certificate in a LocalMachine store called WebHosting. The new options we’re using are to describe the purpose of this certificate and to locate the issuing (root) certificate we generated before:

-eku Describes the purpose of this certificate, which is to authenticate a server. Check here for more information on certificate OID’s.
-is The name of the certificate store where our issuing certificate resides.
-ir The certificate store location of our issuing certificate.
-in The subject name of our issuing certificate.

The result is a certificate that can be used to verify the authenticity of a server, in this case a server named www.sslclientauth.local. The certificate is trusted because it is signed by a trusted (root) certificate as you can see in the following screenshot.

Server certificate

Client certificate

The last certificate we need is the client certificate. Since we already have a root certificate, let’s derive the client certificate from it as well:

makecert -pe -n "CN=SSLClientAuthClient"
         -eku 1.3.6.1.5.5.7.3.2 -is root -ir localmachine -in WebSSLTestRoot
         -ss my -sr currentuser -len 2048

No new makecert are introduced here. The key purpose this time is client authentication and we store the certificate in the CurrentUser personal store.

Client certificate

Configure a test web application

I generated an empty ASP.NET 4.5.1 web project and added a basic ‘hello world’ page. Next step is to configure IIS. We add a new website and configure an https binding as shown in the following screenshot. The physical path points to the website I just created.

Add IIS website

Most important are the https binding, the host name and the certificate. Make sure that host name and certificate match. The certificate that’s selected in the screenshot is the one we created earlier. It can only be selected from the LocalMachine Personal or WebHosting stores, which is why I added the certificate to the latter.

The checkbox Require Server Name Indication (SNI) requires clients (browsers) to use the SNI extension to the TLS protocol.

Last step is to update your hosts file (in %systemroot%\System32\drivers\etc) to include the following line: 127.0.0.1 www.sslclientauth.local. This maps the address www.sslclientauth.local to localhost.

If all went well, you now have a website running with HTTPS. You can easily check this by visiting https://www.sslclientauth.local in a browser. Now for the client authentication part.

Configure client authentication

We already have a client certificate so all we need to do is tell the server that only clients using this particular certificate may enter and configure a client to use the certificate.

To configure the server part, first we must export the public key part of the certificate in base64 format. To do this, right-click your certificate in the MMC Certificate Snap-in and select All Tasks → Export…. Do not export the private key, select the base-64 format and a place to store the certificate. Open the certificate with a text editor, remove the BEGIN and END CERTIFICATE lines and make sure the certificate itself is on one line.

Now that we have the certificate, configure the server to actually use it for authentication. First configure your website to require client certificates:

SSL Settings

Next, open up the Configuration Editor for the website..

Configuration Editor

..and enter the following into the Section: text box: system.webServer/security/authentication/iisClientCertificateMappingAuthentication. Change enabled to True and click on the ellipsis on the right of oneToOneMappings. Click on the Add on the right of the dialog and paste your client certificate value to the right place (make sure it’s really one line of text). Next, enter a valid username and password for your local environment.

One to one mapping config

Exit the dialog and apply the changes. These changes will be applied not to your Web.config file but to your applicationHost.config file (in %systemroot%\System32\inetsrv\config).

Testing

We should now have a valid setup that you can test so we open up a browser and go to https://www.sslclientauth.local. The browser should ask for a certificate:

Browser requests certificate

And we finally have access to our website!

Things that can go wrong

Incorrect username or password

When you do not enter a username and password or you enter incorrect values, the error you receive is a 401.1 – Unauthorized. This may suggest that there is something wrong with your certificate but that doesn’t have to be the case. If you’ve entered incorrect credentials, you’ll see error code 0x8007052e, as in the following screenshot.

Invalid mapped credentials

Base64 client certificate incorrect

You have had to export the client certificate to base64 and then open the file in a text editor, remove the begin and end lines and remove all CRLF’s. Something may have gone wrong in the process so you end up with an incorrect or invalid base64 string. You’ll get a 401.1 – Unauthorized again. However, this time you see either error code 0x80093102 or 0x8009310b.

And finally…

Keep in mind that all we have done is to configure authentication, not authorization! If I present another client certificate that has a valid trust chain, I can gain access to the site as well. In one of the last screenshots you see a certificate named SSLClientAuthClient2. If I select that one, I also see my hello world page. The difference between both access attempts is that with a valid certificate I enter my website with an authenticated principal while with the invalid certificate I’m not authenticated. You’ll have to specify authorization rules for your website or part of your website to actually deny users access.

28 replies
  1. Thiago says:

    Good job!

    Could you please, show how to do client certification authentication in a public scenario?
    In others words, if my site has internet access and i want to authenticate clients with digital certificates issued by a specific CA… how can i do? Mapping one-to-one, in this case, isn’t be able.

    Reply
    • Ronald Wildenberg
      Ronald Wildenberg says:

      First you’d have to obtain a server certificate for identifying your server. That’s standard SSL. The client certificates can be anything you like as long as they are trusted by the server. This means they have to be derived from a (potentially self-signed) certificate that’s installed in the trusted root store on the server.

      Next it’s up to you. You can distribute the same client cert to all your clients and use one-to-one mapping to map this certificate to a single user (why is one-to-one not available by the way??). You can give each client his own cert (and use one-to-one mapping). Or anything in between.

      You can also use many-to-one where you specify rules that determine how certs maps to a user. In both one-to-one and many-to-one it comes down to mapping a certificate to a local (or domain) user on your server (the ‘mapping’ part).

      Reply
  2. Hans-Cees Speel says:

    Nice tutorial thanks. Essentially the same as this for linux: http://www.garex.net/apache/

    But how can you make sure only your issued client certificates have acces? On aopache its this:

    SSLRequireSSL
    SSLRequire %{SSL_CLIENT_S_DN_O} eq “garex AG” and
    %{SSL_CLIENT_S_DN_OU} in {“Fun dept.”}

    but where do you do that with IIS?

    Reply
    • Ronald Wildenberg
      Ronald Wildenberg says:

      In the described one-to-one mapping scenario, a certificate is mapped to a user. It is the user that you should authorize. Authorization of a user can be done in a web application Web.config file on a url basis (e.g.: /Sensitive.aspx is only available for Administrator). Or it can be done in-application if more advanced authorization scenario’s are required.

      The least you should do when configuring this is to ensure only authenticated users have access to your site. This is easily accomplished in the root Web.config of your website. Check here for more info: http://msdn.microsoft.com/en-us/library/8aeskccd(v=vs.100).aspx (users attribute).

      Reply
  3. Dang says:

    Hi Ronald,

    I am trying to configure my https site to accept client certificates, which works when I use an ECA I purchased. However, I need to be able to authenticate with self-signed certificates, but when I log into my site, I’m only prompted for the ECA. The self-signed client certificate doesn’t display in the prompt. The client and server certificate were issued by a self-signed root certificate, which is installed in the trusted root authorities list of the computer account. Using “Require” is not an option in this app since there is some complex business logic that has to get handled by the application. Is there something that I’m missing?

    Reply
    • Ronald Wildenberg
      Ronald Wildenberg says:

      Hi Dang – This can happen when the certificate is not in your personal store on the machine from which you want to access the website, can you verify that? Another reason may be that you did not specify the correct certificate purpose (client authentication). Check out this screenshot from my blog post for details: http://itq.nl/wp-content/uploads/2013/12/04-ClientCert.png.

      Note that if your browser does not present the certificate, this is a problem on the client, not on the server. The browser simply checks your certificate store and presents all certificates eligible for client authentication.

      Reply
  4. Prasad says:

    Hi,

    I have followed all the given steps to create root, server and client certificates. I have hosted sample website with HTML page and did SSL settings, client certificate configuration settings as mentioned.

    Finally, I tried to access the website by selecting the client certificate from the pop-up window. But, I ended with below error:

    HTTP Error 403.16 – Forbidden
    Your client certificate is either not trusted or is invalid.

    Detailed Error Information:
    Module IIS Web Core
    Notification BeginRequest
    Handler ExtensionlessUrlHandler-Integrated-4.0
    Error Code 0x800b0109
    Requested URL https://localhost:443/
    Physical Path E:\SampleRoot
    Logon Method Not yet determined
    Logon User Not yet determined

    Could you please let me know what I missed here.

    Regards,
    M. Prasad Reddy.

    Reply
  5. Sven says:

    Hey,

    do you know, if there is a setting, to only allow one special client certificate (e.g. in your case “WHERE Issuer=’WebSSLTestRoot’” ? I want to suppress the client certificate dialog, because our users choose always the wrong one ^^ It must somehow be possible, because other services of our company do that but not with IIS. Unfortunately it is a big company, so we can’t simply ask them what might be the problem LOL.

    Reply
    • Ronald Wildenberg
      Ronald Wildenberg says:

      This is browser behavior that can not be forced by the server. The default behavior for IE in the intranet zone is not to prompt for a certificate when only one ‘suitable certificate’ exists. A ‘suitable certificate’ is one where the key purpose is client authentication. So if there are multiple client authentication certificates, IE will always show a selection dialog. I don’t know the behavior in other browsers.

      Reply
  6. Eric Belair says:

    This is an excellent explanation. Your spot on about authorization! That’s the only piece of the puzzle that I cannot figure out. I have a website configured for Anonymous access throughout, with the exception of one directory, which is configured for IIS Client Certificate Authentication. When I leave the Authorization Rules set to the default (Allow All Users), anyone with a Client Cert from a trusted source can access it. I tried to remove that rule for the directory and add an Allow rule for the user that is mapped to the client cert, but I get a 401.2 every time. Any idea how to resolve this?

    Reply
  7. Tim Wootton says:

    I have a web site hositng a .net application that we use client side certificate authentication to access but i am deploying this on a salable environment, i am trying to find the best way to allow the web application to scale across multiple servers as required whilst maintaining centralised management of the client certificate mapping. Anyone have any ideas?

    Reply
  8. Katalin Hopkins says:

    Hi, I followed the steps exactly as described and I really appreciate the precise instructions. However, when I got to the end of the configuration steps and did the test, I did get the exact error you had mentioned: 401.1-Unauthorized, and till this day I have not been able to correct that. Would you, or anyone be able to help me resolve that?
    I repeated the same steps on several servers, standalone machines, with a self-signed cert, with a cert authority cert, but keep getting the same error when the under the SSL Settings the Client certificate is marked as Required. If I check the Accept, it works, but when the Required is checked I get the 401.1 error.
    Please help, this is a crucial piece of a large project I am working on, and nothing can go forward unless I get the client cert authentication working. I appreciate any help/suggestion

    Reply
  9. Andy says:

    Really thanks for your tutorial. I followed the steps closely but I also got 401.1 Unauthorized error – You do not have permission to view this directory or page using the credentials that you supplied.

    ModuleName IISCertificateMappingAuthenticationModule
    Notification 2
    HttpStatus 401
    HttpReason Unauthorized
    HttpSubStatus 1
    ErrorCode 2148086018
    ConfigExceptionInfo
    Notification AUTHENTICATE_REQUEST
    ErrorCode ASN1 unexpected end of data. (0x80093102)

    I’ve been searched around but can’t find a hint. Not sure if it is related to the Configuration Editor part. I am using a company computer with domain account. I’ve tried to enter the username and password or leave it blank, or even disable the iisClientCertificateMappingAuthentication but also got the same.

    Do you have any idea where I can look at? Many thanks.

    Reply
  10. German Ernesto Larrosa Fiori says:

    Hi Ronald, first wanted to say that your post helped me a lot to understand a little bit about the use of client and server certificates! just have a couple of doubts about the iis client certifcate mapping autentication.

    I have a system that has Android mobile clients and, on the other hand, a server built based on an asp.net web rest api. What I need to do is to allow only autenticated users to have access to the rest api based only on client certificates (according to our requirements), therefore, I am trying to use the iis client certificate mapping autentication (specifically the one to one option) approach.

    My doubt comes into picture when I have to configure a valid windows username and password on the server side along with the hash of the certificate(when configuring the one to one iiss client certificate mapping autentication), so here comes my questions:

    1 – That username and password need to be a valid window account related to the server where my rest api is deployed ?
    2 – That username and password is related (in some way) with the mobile client that is actually hitting to the rest api ?
    3 – In order to get access to the rest api, a mobile client just need to send a request that contains a valid certificate in it, right ? the username and password configured on the server side has nothing to do with that request, right ?

    Am I understanding this approach in the right way ?

    Thanks in advance,
    German.

    Reply
    • Ronald Wildenberg
      Ronald Wildenberg says:

      Hi German,

      The idea of client certificate mapping authentication is that you map a client certificate to one (oneToOneMappings) or more (manyToOneMappings) users. I only described the oneToOneMapping in my post but manyToOneMappings is similar. The users that you map a certificate to must be valid users on the server that IIS is running on. You can use local users for that.

      These users have no relation whatsoever to your mobile clients. The mobile client just presents a valid certificate. Depending on your requirements you can have multiple setups:

      Every client gets the same certificate which is mapped to a single user.
      Every client gets a unique certificate which is mapped to a single user.
      Every client gets a unique certificate which is mapped to a unique user.
      Every client gets a unique certificate but you map certificate groups to users.

      Each has its advantages/disadvantages of course.

      Reply
        • German Larrosa says:

          Hi Ronald,

          I configured my environment according to what you explained above but for some reason I couldn’t make it to work since every time I try to access to my site I get a 402.1 http error (You are not authorized to view this page due to invalid authentication headers.)

          I disable all of the authentication methods that IIS allows to set throught its UI (anonymous, impersonation, basic, forms and windows authentication) as my site was configured to only authenticate using iisClientCertificateMappingAuthentication, is that ok ?

          As a note, if I enable anonymous authentication method I do have access to the site but I think that no client certificate authentication is being applied in this case since I always get access to the site regardless if the hash of the stored certificate (iis client certifiate configuration for one to one) is valid or not.

          My environment is iis 10 and windows 10.

          Any thoughts ?

          Thanks again,
          German.

          Reply
          • Ronald Wildenberg
            Ronald Wildenberg says:

            Pfew, tough questions 🙂

            I suppose you mean 401.2 instead of 402.1? You should be able to switch off all other authentication methods without issues, especially Anonymous (since this would allow everyone access to your site). Can you access your site via a browser? Or maybe through Fiddler? Here‘s how to configure Fiddler with a client certificate.

            I think maybe your problem is not in the server-side configuration but on the client. Trying other means of accessing your site (browser/Fiddler) should tell you where the problem is.

          • German Larrosa says:

            Hi Ronald,

            Finally got it to work!.. as far as I know the problem was caused by two things:

            1 – The configuration for the iisClientCertificateMappingAuthentication, I was using the ApplicationHost.config instead of the site web.config to make the changes.

            2 – I was using an AD user instead of a local one when configuring the iisClientCertificateMappingAuthentication section (oneToOneMapping field)

            Thanks again!
            Regards,
            Geman Larrosa.

  11. Brian Polk says:

    I stumbled upon this forum because i’m working on trying to get client certificate auth working cross platform with iOS clients to an IIS server. Needless to say, this has been a challenge. But I thought I could add something to this discussion that I recently learned (and I did not see mentioned in this thread.) Regarding the client cert, it’s important to have both the right purpose (1.3.6.1.5.5.7.3.2 as mentioned by the author) however the “Key Usage” property is equally important. If you view your client cert and look at the details, you should see Key Usage often with a ! in a yellow triangle. This indicates a critical property. In order for a web browser to serve up that cert, the Key Usage must have “Digital Signature (80)” included. Depending on the method you are using to generate the cert and the Cryptographic Service Provider (CSP) you may have a choice (or limit) on the key usage. You may see only “Signature” or “Exchange” or sometimes both. This is common with generating a cert via a Windows Server domain’s local CA through the web interface. If your Key Usage is only Exchange/Encipherment your browser will not try to use that cert for authentication.

    Hopefully this helps someone who might have this issue. I spent a lot of hours trying to get around this before finally noticing the Key Usage property.

    Good luck and if anyone has any experience getting client cert auth to work on iOS devices, PLEASE hit me up 🙂

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *

*