Certificates are easily deployed in a Active Directory (AD) infrastructure but using them to manage accesses, especially to websites hosted on an Internet Information Services (IIS) server can be challenging due to the lack of good documentation on the Internet. This is why I created this tutorial that can also be used as a small cheat sheet.
Since this feature is part of the Transport Layer Security (TLS) standard most servers such as IIS, Apache, Nginx support this feature natively. Popular browsers (Internet Explorer, Chrome, Firefox, etc.) also support this feature natively.
This tutorial will teach you how to configure this feature on a Internet Information Services (IIS) server.
Why should I use this feature?
This feature adds a layer of authentication in front of all of your web sites or can be configured to a subset of your web sites. This feature is especially useful to increase security to highly sensitive web sites. TLS is generally used to guarantee the connection to a server is secure. It is however also possible for a server to validate that only specific clients (eg. browsers) can connect to it.
Is it really secure?
This form of authentication algorithm is enforced mathematically with asymmetric cryptography. TLS (formerly known as SSL) client authentication has been part of the Transport Layer Protocol for a long time and is an industry proven standard for secure communications.
This feature is also often used for compliance in a large organization that need to make sure that only authorized users can access internal websites.
Requirements
Here is what you need for this tutorial:
- A Certificate Authority certificate
- A Server certificate
- One or more Client certificate(s) (for users)
Before You Begin
If you need to generate the certificates, please view my previous blog post. After that is done, complete the following:
-
Install the ca.crt (public key) file in the following IIS server certificate store:
Local Computer → Trusted Root Certification Authorities -
You will need to merge the server.crt (public key) and server.key (private key) files into a single file named server.pfx with the following command line:
openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt
You will be prompted to enter a password; make sure you use a strong one.
Install the resulting server.pfx file in the following IIS server certificate store:
Local Computer → Personal -
Each client that will access the server needs a certificate. Just like the server certificate above, both the public key (.crt) and private key (.key) will need to be merged into a single
.pfx file. The.pfx file will need to be installed on the user’s computer in the following store:
Current User → Personal
I’ve tried to simplify this tutorial into easy to follow steps. I also show how to do it manually and also via PowerShell scripts. Take care to modify the scripts to match your environment.
How to Configure IIS
Step 1 - Enabling the required features
Enable IIS Client Certificate Mapping Authentication in the windows features dialog in the Internet Information Services → World Wide Web Services → Security section. (View Image 1)
The Windows features dialog can be opened using the following shortcut:
WIN + R -> optionalfeatures
On a Windows Server, you can enable this feature in the server configuration manager.
It can also be enabled using the following PowerShell command :
Enable-WindowsOptionalFeature -Online -FeatureName IIS-IISCertificateMappingAuthentication
Step 2 - Configure a HTTPS binding
Configure your SSL certificate in the Site binding dialog in the IIS Manager. To open the Side Binding dialog, you must select the website where you want to enable this feature then click on Bindings.... Lastly, you must add a HTTPS binding and select your server certificate. An example is shown below (image 2 and 3):
Default Web Site → Bindings… → Add…
It can also be done with a few simple PowerShell commands:
# List certificates in the local machine personal store.
Get-ChildItem -Path CERT:LocalMachine/My
Thumbprint Subject
---------- -------
838E34D06C2FB5C80E99E6B6938C4127134B32A5 CN=localhost
6A11EAFFBB6A7E1F3CE11DAE82956D4F2973320E CN=mathmo.org, O="MathMoOrganisation, Inc.", S=CA, C=US
# Create HTTPS binding if it doesn't exists
New-WebBinding -name "Default Web Site" -Protocol https -Port 443
# Get the bindings
$bindings = Get-WebBinding -Name "Default Web Site"
# Configure the certificate mathmo.org for the bindings
$bindings.AddSslCertificate("6A11EAFFBB6A7E1F3CE11DAE82956D4F2973320E",'My')
Step 3 - Enforce SSL on the website
Make sure that your website requires SSL and requires a client certificate. This can be done by opening the SSL settings. To open the SSL settings you must select your website where you want to enable this feature, filter for the SSL settings, select it and click on Open Feature. In the examples show below (see image 4 and 5) the flow goes like this:
Default Web Site → Filter SSL Settings → Select SSL Settings → Open Feature
It can also be done with a PowerShell command:
Set-WebConfiguration -Location "Default Web Site" -Filter "system.webserver/security/access" -Value "Ssl,SslNegotiateCert, SslRequireCert"
Step 4 - Disable Anonymous Authentication
Make sure that you disable Anonymous authentication on your web site by going into the Authentication settings. In the examples show below (Image 6 and 7):
Default Web Site → Authentication → Open Feature
PowerShell command:
Set-WebConfigurationProperty -filter "/system.WebServer/security/authentication/AnonymousAuthentication" -name enabled -value false -location "Default Web Site"
Step 5 - Enable client authentication in IIS
You are now ready to enable the feature on your website!
5.1 - Start by opening your website Configuration Editor.
5.2 - Go to the system.webServer/security/authentication/iisClientCertificateMapping Authentication section (see image 9).
5.3 - Here you can choose to enable manyToOneCertificateMappingsEnabled or oneToOneCertificateMappingsEnabled (see image 10).
PowerShell
# enable certificate mapping authentication for Default Web Site
Set-WebConfigurationProperty -filter "/system.webServer/security/authentication/iisClientCertificateMappingAuthentication" -name enabled -Value true -location "Default Web Site"
# enable oneToOneCertificateMappings for Default Web Site
Set-WebConfigurationProperty -filter "/system.webServer/security/authentication/iisClientCertificateMappingAuthentication" -name oneToOneCertificateMappingsEnabled -Value true -location "Default Web Site"
We recommend the oneToOneCertificateMappings, as it requires users to have their own certificate and it is safer. However, manyToOneMappings can also be used. It will reduce the amount of management required, but it is a compromise on the security side of things. Having a single client certificate for a team or a group of users will increase the risk of it being leaked or compromised. The client certificate private key normally must stay on the endpoint where it has been generated.
5.4 - Open the oneToOneMappings Configuration
5.5 - In the dialog you can configure each user with their base64 encoded certificate public key** (instructions on how to obtain it are provided at the end of this article) and their active directory (AD) credentials (see images 11 and 12).
PowerShell
# get the oneToOneMappings collection
$collection = Get-IISConfigSection -SectionPath "system.webServer/security/authentication/iisClientCertificateMappingAuthentication" -Location "Default Web Site" | Get-IISConfigCollection -CollectionName "oneToOneMappings"
$username = Read-Host "Username?"
$password = Read-Host "Password?"
$b64CertificatePublicKey = Read-Host "Base64 Certificate Public key?"
# create mapping in the oneToOneCertificateMappings
New-IISConfigCollectionElement -ConfigCollection $collection -ConfigAttribute @{"enabled" = "True"; "userName" = $username; "password" = $password; "certificate" = $b64CertificatePublicKey}
Make sure that the user has read access to the site folder!
5.6 - Close the Collection Editor and Apply the New Configuration Editor Settings (see image 13).
It is recommended that you restart your website.
Results
If all went well, accessing the website using a popular browser should prompt you a dialog to choose a certificate to authenticate before accessing the server.
Additional Resources:
Note: If you followed this blog to generate self-signed certificates, then the client public key is located in the client1.crt file. The header -----BEGIN CERTIFICATE----- and footer -----END CERTIFICATE----- and line breaks must be removed.
View the example below:
This file client1.crt
-----BEGIN CERTIFICATE-----
MIICUjCCAfegAwIBAgIUbfEfctjOiwDqqBR1vupzjdN4qI0wCgYIKoZIzj0EAwIw
gZ8xCzAJBgNVBAYTAkNBMQswCQYDVQQIDAJRQzESMBAGA1UEBwwJTGF2YWx0cmll
MRkwFwYDVQQKDBBEZXZvbHV0aW9ucyBpbmMuMREwDwYDVQQLDAhTZWN1cml0eTEY
MBYGA1UEAwwPZGV2b2x1dGlvbnMubmV0MScwJQYJKoZIhvcNAQkBFhhzZWN1cml0
eUBkZXZvbHV0aW9ucy5uZXQwHhcNMjAwNjI1MTUwMjMyWhcNMjMwMzIyMTUwMjMy
WjCBlzELMAkGA1UEBhMCQ0ExCzAJBgNVBAgMAlFDMRIwEAYDVQQHDAlMYXZhbHRy
aWUxGTAXBgNVBAoMEERldm9sdXRpb25zIGluYy4xETAPBgNVBAsMCFNlY3VyaXR5
MREwDwYDVQQDDAhKb2huIERvZTEmMCQGCSqGSIb3DQEJARYXSm9obkRvZUBkZXZv
bHV0aW9ucy5uZXQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT/kLSLRnKIdewU
9Ze8KuZbuz7y1PfhTMEfV7ZQ3gRfSxGdRBxftaNFPtxjkmO9hVowyptUR8UvGc9I
a8rRX6NwoxcwFTATBgNVHSUEDDAKBggrBgEFBQcDAjAKBggqhkjOPQQDAgNJADBG
AiEAwvtbZNwzaf1RMvanSGorJwxYSSBiPIUg0YmyfIpG6pwCIQCoE9+V3/2ULCj9
NtzEYsW2uPojMQ3ddr1CpE2m07yIdQ==
-----END CERTIFICATE-----
Should give you the following result:
MIICUjCCAfegAwIBAgIUbfEfctjOiwDqqBR1vupzjdN4qI0wCgYIKoZIzj0EAwIwgZ8xCzAJBgNVBAYTAkNBMQswCQYDVQQIDAJRQzESMBAGA1UEBwwJTGF2YWx0cmllMRkwFwYDVQQKDBBEZXZvbHV0aW9ucyBpbmMuMREwDwYDVQQLDAhTZWN1cml0eTEYMBYGA1UEAwwPZGV2b2x1dGlvbnMubmV0MScwJQYJKoZIhvcNAQkBFhhzZWN1cml0eUBkZXZvbHV0aW9ucy5uZXQwHhcNMjAwNjI1MTUwMjMyWhcNMjMwMzIyMTUwMjMyWjCBlzELMAkGA1UEBhMCQ0ExCzAJBgNVBAgMAlFDMRIwEAYDVQQHDAlMYXZhbHRyaWUxGTAXBgNVBAoMEERldm9sdXRpb25zIGluYy4xETAPBgNVBAsMCFNlY3VyaXR5MREwDwYDVQQDDAhKb2huIERvZTEmMCQGCSqGSIb3DQEJARYXSm9obkRvZUBkZXZvbHV0aW9ucy5uZXQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT/kLSLRnKIdewU9Ze8KuZbuz7y1PfhTMEfV7ZQ3gRfSxGdRBxftaNFPtxjkmO9hVowyptUR8UvGc9Ia8rRX6NwoxcwFTATBgNVHSUEDDAKBggrBgEFBQcDAjAKBggqhkjOPQQDAgNJADBGAiEAwvtbZNwzaf1RMvanSGorJwxYSSBiPIUg0YmyfIpG6pwCIQCoE9+V3/2ULCj9NtzEYsW2uPojMQ3ddr1CpE2m07yIdQ==
I hope this article was helpful to you guys and let me know if you would like me to create a tutorial to enable this feature on Apache, Nginx or other servers!