How to setup client certificate with certificate chain Authentication in IIS

Prerequisites

  • Windows Server 2016 or above with installed:
    • Powershell
    • IIS
    • WireShark
    • Chrome browser
  • Assign your PC a hostname, for example dev-example.
    • Restart of PC is required
  • Active Directory
    • Add your PC to a domain (for example to a test domain e.g. contoso.com)
      • Requires DNS setup - in lab you can use hosts file.
      • Sometime restart of PC is required before you will be able to ad it to domain.

Generate certificates

Run this command to generate required certificates and install them in proper (LM/CU) certificates stores.

.\generate-cert.ps1 -hostname "dev-example" -domain "contoso.com" -prefixName "CUST-0001-" -password 'Pa$$word'

The script will output all crt, pfx files into Out dir. Some scripts will be also automatically installed to Local-Machine and Current-User certificate stores.

Configure hosts file

  1. Run Notepad.exe as Administrator and open from %systemroot%\System32\drivers\etc a host file. (Use All Files (*.*))
  2. Add entry 127.0.0.1 and FQDN of your PC (e.g. dev-example.contoso.com)
    127.0.0.1    dev-example.contoso.com

Add Feature IIS Client Certificate Mapping Authentication

To allow user to authenticate with client certificate authentication we need to enable Client Certificate Mapping Authentication in Windows Feature. Enable Client Certificate Mapping Authentication

Configure IIS

How to install an SSL/TLS Certificate in IIS

Prerequisites

  1. In IIS Manager in the left Connections menu, select the server name (host) where you want to install the certificate.
  2. In the center menu, click the Server Certificates icon under the Security section near the bottom. Select Server Certificates
  3. In the right Actions menu, click Import.... Select Server Certificates Import
  4. In the Import Certificate dialog click ... button to browse Server Certificate private key (*.pfx) file created by generate-cert.ps1 script. Select Server Certificates Import Select
  5. Enter Private key password - it should be the same as you provided during run of generate-cert.ps1 script.
  6. Leave Personal Certificate Store and press OK button.

Configure SSL Settings

  1. In IIS Manager in the left Connections menu, click SSL Settings. SSL Settings
  2. In opened settings check Require SSL and under Client Certificate choose Require. SSL Settings
  3. To Save click on Apply button under Actions panel.

Binding SSL Certificate to Web Application

  1. From the left Connections menu, expand your server’s name, expand the Sites folder, and then select the site (e.g. Default Web Site) that you want to secure.
  2. In the right Actions menu, click Bindings… Select Server Certificates Import Select
  3. In opened dialog click Add button and enter FQDN (e.g. dev-example.contoso.com) into Hostname filed.
  4. From SSL Certificate dropdown select installed in the previous section Server Certificate.
  5. Then click OK button and Close.

Convert Client Certificate to base 64 format

Run this command to generate base_64 version of a certificate. (assuming that client cert name was CUST-0001-ClientCertificate.crt)

& .\Out\certutil.exe -encode "CUST-0001-ClientCertificate.crt" ".\Out\CUST-0001-ClientCertificate_base64.crt"

Map Client Certificate

  1. In order to configure the server to know which client certificate it needs to validate in IIS Manager in the left Connections menu, expand your server’s name, expand the Sites folder, and then select the site (e.g. Default Web Site).
  2. Click on Configuration Editor. Configuration Editor
  3. In opened settings from dropdown choose system.webServer/security/authentication/iisClientCertificateMappingAuthentication and enable the setting then Apply changes. Configuration Editor Mapping

Many-to-one

  1. To add new mapping click ... Configuration Editor Mapping
  2. Fill out the properties for a mapping and repeat for each user you want to configure for access or denial. Remember that you need the client certificate and root CA certificate installed on all the user’s mmc. (In order for this to work you need to enter a valid username and password) Configuration Editor Mapping ManyToOne
  3. Now we need to create some rules to go with this mapping so the server can determine if a client is allowed in or not. It’s a so click on the rules property and the ...button. Configuration Editor Mapping ManyToOne Add Rules
  4. Add as many rules you like - on below example we have two rules where the server will check the client certificate to see if it’s signed by the correct CA Issuer (e.g. dev-example.local) and Subject (e.g. dev-example). For more details please visit the IIS Many-To-One Mapping reference for more documentation. Configuration Editor Mapping ManyToOne Add Rules CN
  5. When you don Apply all changes. Configuration Editor Mapping Apply

One-To-Many

This approach means that we need an individual client certificate for each user mapping. You can either disable the many-to-one mapping and use the same certificate and user or create new ones.

  1. Go to the Configuration Editor and open the system.webServer/security/authentication/iisClientCertificateMappingAuthentication section.
  2. Click the ... button of the oneToOneMappings. Configuration Editor Mapping OneToMany
  3. To Add new mapping we need public key of SSL Certificate - we exported it to base64 format already in step Convert Client Certificate to base 64 format. Open a file in notepad .\Out\CUST-0001-ClientCertificate_base64.crt. Configuration Editor Mapping OneToMany Base64
  4. Remove opening and closing tags
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
  1. Replace all new line characters so the certificate could be in a single line. Alternatively you can use Notepad++ and replace all occurrence of \r\n (new line characters) with empty string. Configuration Editor Mapping OneToMany Add Base64 Line
  2. The final result should look like this. Configuration Editor Mapping OneToMany Add Base64 Line Final
  3. Now copy the line and fill oneToMany entires. Paste copied certificate to certificate property of a new entry - provide a user which has required access permission to web application. (You can map this way as many client certificate as you want.) Configuration Editor Mapping OneToMany Add Cert
  4. When you don close the dialog and Apply changes. Configuration Editor Mapping Apply

Require Certificate Request for during TLS handshake (Enable Negotiate Client Certificate)

Force IIS to require Certificate Request during TLS handshake.

  1. Run cmd as Administrator
  2. Assuming that FQDN of your host PC is dev-example.contoso.com run commands to get Application ID and Certificate Hash values for a sslcert configuration which Hostname:port equls dev-example.contoso.com.
netsh http show sslcert hostname=dev-example.contoso.com:443

Output should look like this:

SSL Certificate bindings:
-------------------------

    Hostname:port                : dev-example.contoso.com:443
    Certificate Hash             : <your_certificate_hash>
    Application ID               : {<your_web_app_id>}
    Certificate Store Name       : MY
    Verify Client Certificate Revocation : Enabled
    Verify Revocation Using Cached Client Certificate Only : Disabled
    Usage Check                  : Enabled
    Revocation Freshness Time    : 0
    URL Retrieval Timeout        : 0
    Ctl Identifier               : (null)
    Ctl Store Name               : (null)
    DS Mapper Usage              : Disabled
    Negotiate Client Certificate : Disabled <-- We need to enable this one
    Reject Connections           : Disabled
    Disable HTTP2                : Not Set
  1. Delete the sslcert configuration.
netsh http delete sslcert hostnameport=dec-example.contoso.com:443
  1. Create the sslcert configuration but this time with enabled Negotiate Client Certificate.
netsh http add sslcert hostnameport=dec-example.contoso.com:443 certhash=<your_certificate_hash> appid={<your_web_app_id>} certstorename=MY verifyclientcertrevocation=enable VerifyRevocationWithCachedClientCertOnly=disable UsageCheck=enable clientcertnegotiation=enable
  1. Check the result of our work.
netsh http show sslcert hostname=dev-example.contoso.com:443

Output should look like this:

SSL Certificate bindings:
-------------------------

    Hostname:port                : dev-example.contoso.com:443
    Certificate Hash             : <your_certificate_hash>
    Application ID               : {<your_web_app_id>}
    Certificate Store Name       : MY
    Verify Client Certificate Revocation : Enabled
    Verify Revocation Using Cached Client Certificate Only : Disabled
    Usage Check                  : Enabled
    Revocation Freshness Time    : 0
    URL Retrieval Timeout        : 0
    Ctl Identifier               : (null)
    Ctl Store Name               : (null)
    DS Mapper Usage              : Disabled
    Negotiate Client Certificate : Enabled
    Reject Connections           : Disabled
    Disable HTTP2                : Not Set

Useful links

SSL/TLS Handshake

Set Client Negotiation Certificate

Client Certificate Authentication

New-SelfSignedCertificate

Tools

PowerShell

Issues