Client certificate authentication means that the caller does not prove its identity with a name, a password or a token, but with a certificate stored in its certificate store. The verification is performed by the IIS web server before the request reaches the application — the API code therefore only runs for calls that have passed the certificate check.
It is used for APIs published to the internet where the other party insists on a certificate instead of a token — typically banks, government institutions and large customers running their own certification authority. The whole procedure applies to any web application hosted on IIS, including NET Genium itself.
Certificates and tokens do not exclude each other. A certificate authenticates the device or system that connects and is handled by IIS; a token authenticates the particular client and is handled by the application code — a detailed description of tokens is provided in the separate API guide. Both layers are commonly combined: the certificate proves the other party's server, the token the particular integration.
1. How the verification works
- The client opens an HTTPS connection and the server sends it the list of certification authorities it trusts.
- The client picks a certificate issued by one of them — a browser displays a certificate selection dialog, an application takes the certificate from its configuration — and proves possession of the matching private key.
- IIS validates the certificate and builds the chain up to the root authority. That authority must be present in the “Trusted Root Certification Authorities” store of the server, otherwise the verification fails.
- Depending on the IIS settings, the verified certificate is then handled in one of two ways:
| Variant | What is configured | When to choose it |
| Mapping to a Windows user account | An IIS role and a mapping in the site configuration; the application is not changed | The request has to run under a particular Windows account, or the application must not be modified because of authentication |
| Verification in the application code | IIS settings and a few lines of code | The application is to decide on its own whom the certificate belongs to and answer accordingly (typically an API) |
The following is required:
- certificates — supplied by the other party, or your own test ones (see the next chapter),
- the “IIS Client Certificate Mapping Authentication” IIS role (only for mapping to a Windows account),
- the “MMC” console for installing certificates,
- PowerShell running as administrator.
2. Certificates
Three certificates in different roles take part in the whole procedure:
| Certificate | Where it is stored | What it is for |
| Root (certification authority) | On the server, in the “Trusted Root Certification Authorities” store of the computer | The server uses it to verify that the client certificate was issued by an authority it trusts |
| Server | On the server, in the “Personal” store of the computer | The SSL certificate set in the site binding (HTTPS) |
| Client | On the client computer, in the “Personal” store of the user (for a service, of the account it runs under) | The client proves its identity with it |
In production the client certificate is supplied by the other party, or obtained from a public certification authority. The root certificate is usually part of the supplied file; if it is not, it has to be requested separately and installed on the server — without it the chain cannot be verified.
2.1. Creating test certificates
For development and testing the certificates can be generated on your own (so called self-signed certificates). They serve to try out the whole chain; they do not belong in production, because nobody except your server knows their root authority.
Certificates are generated with the “New-SelfSignedCertificate” command in PowerShell running as administrator. The procedure has three steps: the root authority is created first and then signs both the server and the client certificate.
# 1) Root certification authority
$ca = New-SelfSignedCertificate `
-Type Custom `
-Subject "CN=Example Test CA" `
-KeyUsage CertSign, CRLSign, DigitalSignature `
-KeyLength 4096 `
-HashAlgorithm SHA256 `
-KeyExportPolicy Exportable `
-CertStoreLocation Cert:\LocalMachine\My `
-NotAfter (Get-Date).AddYears(10) `
-TextExtension @("2.5.29.19={text}CA=true")
# 2) Server certificate signed by the same authority
$server = New-SelfSignedCertificate `
-Type SSLServerAuthentication `
-Subject "CN=api.example.com" `
-DnsName "api.example.com" `
-KeyLength 2048 `
-HashAlgorithm SHA256 `
-KeyExportPolicy Exportable `
-CertStoreLocation Cert:\LocalMachine\My `
-Signer $ca `
-NotAfter (Get-Date).AddYears(2)
# 3) Client certificate signed by the same authority
$client = New-SelfSignedCertificate `
-Type Custom `
-Subject "CN=Client XY" `
-KeyUsage DigitalSignature, KeyEncipherment `
-KeyLength 2048 `
-HashAlgorithm SHA256 `
-KeyExportPolicy Exportable `
-CertStoreLocation Cert:\LocalMachine\My `
-Signer $ca `
-NotAfter (Get-Date).AddYears(2) `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2")
- The “-DnsName” parameter of the server certificate writes the domain into the “Subject Alternative Name” extension. Without it today's browsers reject the certificate — the “CN” alone is no longer accepted as the server name. List all addresses the site will run on (the parameter also accepts several values separated by commas).
- The “2.5.29.37” extension of the client certificate is “Extended Key Usage” and the “1.3.6.1.5.5.7.3.2” value means “Client Authentication” — the very purpose the certificate is created for.
- The root authority is created without the “Extended Key Usage” extension, so that it can sign a certificate for any purpose.
The certificates are then exported into files — the root and client public keys (the “cer” extension) and the client certificate including its private key (the “pfx” extension, protected by a password):
$password = Read-Host -AsSecureString -Prompt "Password for the PFX file"
Export-Certificate -Cert $ca -FilePath C:\cert\CARoot.cer
Export-Certificate -Cert $client -FilePath C:\cert\ClientCert.cer
Export-PfxCertificate -Cert $client -FilePath C:\cert\ClientCert.pfx -Password $password
Older procedures used the “makecert.exe” and “pvk2pfx.exe” programs for the same purpose. These have long been retired, are not part of today's Windows and cannot write the “Subject Alternative Name” extension — do not use them.
2.2. Installing the certificates on the server
- Run the “MMC” console (type “mmc” into the search box) as administrator.
- In the “File” menu choose “Add/Remove Snap-in…” (Ctrl+M), select “Certificates” and add it with the “Add” button.
- Choose “Computer account”, “Local computer” and confirm with “Finish” and “OK” — server certificates always belong to the computer store, not to the store of the signed-in user.
- Right-click the “Trusted Root Certification Authorities” folder, choose “All Tasks / Import…” and import the root certificate (for example “CARoot.cer”).
- Import the server certificate including its private key (for example “ServerCert.pfx”) into the “Personal” folder the same way.
If the certificates were generated directly on this server with the command from the previous chapter, they are already in the “Personal” store of the computer — only the root certificate (the exported “CARoot.cer” file) then has to be imported into the “Trusted Root Certification Authorities” folder.
2.3. Installing the client certificate
The client certificate is installed on the computer or server the calls will be made from:
- Run the “MMC” console and add the “Certificates” snap-in the same way as above.
- Choose “My user account” if the signed-in user is to present the certificate (typically a browser), or “Computer account” if a service or a scheduled task is.
- Import the client certificate including its private key (for example “ClientCert.pfx”) into the “Personal” folder.
- When the certificate is installed into the computer store, grant the account the calling application runs under access to the private key — right-click the certificate, “All Tasks / Manage Private Keys…”. Without it the application can see the certificate but cannot present it.
- If the client computer does not trust the issuer of the server certificate (typically with test certificates), import the root certificate into its “Trusted Root Certification Authorities” folder as well.
3. IIS settings
3.1. Installing the role
Mapping a certificate to a Windows account is handled by a separate web server role that has to be installed:
- Run “Server Manager” and choose “Add roles and features”.
- In the “Server Roles” step expand “Web Server (IIS) / Web Server / Security” and check “IIS Client Certificate Mapping Authentication”.
- Finish the wizard with the “Install” button.

The list also contains a similarly named “Client Certificate Mapping Authentication” role (without the leading “IIS”). That one maps certificates to accounts through Active Directory and is configured differently; the procedure in this guide does not use it.
If the certificate is to be evaluated in the application code (see chapter 4), the role is not needed at all.
3.2. Setting up the HTTPS binding
- Run “IIS Manager” and select the target site in the “Sites” list.
- In the “Actions” pane choose “Bindings…” and add an “https” binding on port 443 with the “Add…” button.
- In the “SSL certificate” field select the server certificate installed in the previous chapter.
A detailed description of obtaining an SSL certificate from a certification authority is provided in the separate Installing NET Genium on the web server guide.
3.3. Requesting the client certificate
- In “IIS Manager” select the application (or the whole site) that is to be protected by the certificate and open “SSL Settings”.
- Check “Require SSL” and choose one of the options in the “Client certificates” section:
| Option | Behaviour |
| Ignore | No certificate is requested from the client (the default state) |
| Accept | The certificate is requested, but the request passes even without it — the evaluation is up to the application |
| Require | Without a valid client certificate the server rejects the request with the 403.7 status code |

The “Require” option belongs to mapping onto a Windows account, the “Accept” option to evaluation in the application code — it lets the application answer with its own error message instead of a server page.
3.4. Mapping a certificate to a Windows account (one-to-one)
A one-to-one mapping assigns a particular Windows account to a particular certificate. It is configured in the site configuration, not in the source code of the application:
- In “IIS Manager” select the site the application runs under in the “Sites” list and open “Configuration Editor”.
- In the “Section” field select “system.webServer/security/authentication/iisClientCertificateMappingAuthentication”.
- Set “enabled” to “True” and “oneToOneCertificateMappingsEnabled” to “True”.
- Click “…” at the “oneToOneMappings” item, add a rule with the “Add” button and fill in:
- “enabled” — “True”
- “userName” — the Windows account the request is to run under (usually the same service account the application pool runs under)
- “password” — the password of that account
- “certificate” — the public key of the client certificate encoded in Base64 (see below)
- Save the changes with the “Apply” button.


The most reliable way to obtain the value for the “certificate” field is PowerShell — the result is one long line without any line breaks, ready to be copied:
[Convert]::ToBase64String([System.IO.File]::ReadAllBytes("C:\cert\ClientCert.cer"))
- The certificate must be exported without the private key (a “cer” file). The private key is known to the client only.
- Opening the file in a text editor shows the same string — but without the “-----BEGIN CERTIFICATE-----” and “-----END CERTIFICATE-----” lines and without line breaks. Editing it by hand is therefore unnecessary and error-prone.
The “iisClientCertificateMappingAuthentication” section cannot be set in the “Web.config” file of the application. It is locked in the server configuration (the “overrideModeDefault” attribute has the “Deny” value), which is why “Configuration Editor” is opened at the server or site level — not at the level of a nested application. The values are written into the “applicationHost.config” file.
3.5. Mapping several certificates to one account (many-to-one)
A many-to-one mapping does not compare the whole certificate, only selected fields — typically the issuer and the subject. It is configured in the same “Configuration Editor” section, only “manyToOneMappings” is filled in instead of “oneToOneMappings” and “manyToOneCertificateMappingsEnabled” is turned on. Besides the account and the password, each rule also holds a list of rules (“rules”) with the certificate field, the compared value and a flag saying whether the value has to match exactly.
This variant suits every situation where the certificates are issued by a single authority and there are several of them or they get replaced — the rule survives a certificate renewal, whereas a one-to-one mapping has to be rewritten with the new public key after it.
4. Verifying the certificate in the application code
The second variant needs neither the IIS role nor a Windows account. “Client certificates: Accept” (or “Require”) is set in “SSL Settings” and the application evaluates the certificate itself — in an API that means the “Application_BeginRequest” method in the “Global.asax.cs” file described in the API guide:
System.Web.HttpClientCertificate cert = Request.ClientCertificate;
if (!cert.IsPresent || !cert.IsValid)
{
throw new UnauthorizedAccessException("Missing or invalid client certificate");
}
string thumbprint = BitConverter.ToString(cert.GetCertHash()).Replace("-", "");
if (!"A1B2C3…".Equals(thumbprint, StringComparison.OrdinalIgnoreCase))
{
throw new UnauthorizedAccessException("Unknown client certificate: " + cert.Subject);
}
- The “IsPresent” property tells whether the client sent a certificate at all, “IsValid” whether it passed the verification on the IIS side.
- The thumbprint is the strictest criterion — it identifies exactly one certificate, so the value in the application has to be changed after a renewal. A looser criterion is the “Issuer” and “Subject” pair, which survives a certificate renewal.
- The list of allowed certificates does not belong in the source code — store it in the database (the same way as API tokens in the “ng_apitoken” table) or in a configuration file, so that a new counterparty can be added without recompiling the application.
- This check does not replace the IIS settings. If “SSL Settings” is left at “Ignore”, no certificate ever arrives and the “IsPresent” property is always false.
5. Proxy server and revocation checking
If the certificate contains a certificate revocation list (“CRL”) or the address of an “OCSP” service, the server downloads these addresses from the internet while building the chain. Without direct internet access the verification is delayed and eventually fails, even though the certificate itself is fine.
Windows has two independent proxy server settings and the second one governs this check:
- WinINet — the setting used by browsers and interactive applications (the “Internet Options” dialog). It has no effect on certificate verification.
- WinHTTP — the setting used by system services, including the certificate validity check. This is the one that has to be set.
The current state is displayed and set in a command line running as administrator:
netsh winhttp show proxy
netsh winhttp set proxy proxy.example.com:8080 bypass-list="<local>"
If the first command prints “Direct access (no proxy server)” and the server has no direct internet access, the proxy server has to be set with the second command. The address of the proxy server is supplied by the customer's network administrator.
6. Troubleshooting
The authentication takes place at the IIS level, so no failed attempt appears in the log of the application or of NET Genium — the cause has to be looked for in the status code of the response and in the IIS logs.
6.1. Response status codes
| Code | Meaning and what to check |
| 403.7 | The client sent no certificate — it is not installed, it lacks “Client Authentication”, or the client did not offer it because the server did not list its issuer as trusted |
| 403.13 | The certificate is revoked, or its revocation status could not be checked (see chapter 5) |
| 403.16 | The certificate cannot be trusted — the root authority is missing from the server store, or the store holds certificates that do not belong there (see chapter 6.3) |
| 401.1 | The certificate was mapped, but signing in with the mapped account failed — a wrong name or password in the mapping |
6.2. IIS logging
Details of a rejected request are written by “Failed Request Tracing”:
- In “IIS Manager” select the site and choose “Failed Request Tracing…” in the “Actions” pane; check “Enable” and confirm the directory for the logs.
- Open “Failed Request Tracing Rules” at the application in question and add a rule with the “Add…” button — usually for “All content” and for the “401-403” status codes.
- Repeat the failed request and open the resulting “fr…xml” file in a browser.
If the certificate did reach the application, its values are listed by the “Headers” report in the NET Genium tools — it shows the contents of the “Request.Headers”, “Request.Cookies” and “Request.ClientCertificate” collections. A detailed description of the reports is provided in the separate Reports guide.
6.3. Contents of the trusted root store
The “Trusted Root Certification Authorities” store may only hold self-signed certificates — that is, genuine root authorities. A certificate that does not belong there can break client certificate verification even though everything else is set up correctly.
Such certificates are recognised by different values in the “Issued to” and “Issued by” columns. PowerShell lists them:
Get-ChildItem Cert:\LocalMachine\Root |
Where-Object { $_.Issuer -ne $_.Subject } |
Format-List Subject, Issuer, Thumbprint
If the command lists any certificate, move it to the store it belongs to (usually “Intermediate Certification Authorities”), restart the server and repeat the attempt.
6.4. Other common causes
- A renewed certificate. Both the one-to-one mapping and the thumbprint check in the code are bound to a particular certificate. Authentication stops working after a renewal and the new public key or thumbprint has to be written in; a many-to-one mapping by issuer and subject is immune to this.
- Configuration moved to another server. The password in the mapping is encrypted in the “applicationHost.config” file with a key of that particular server, so a copied configuration does not work on another server — the mapping has to be filled in again.
- The certificate is not offered in the browser at all. A client only offers certificates issued by an authority from the list the server sent it. If the root authority is missing from the server store, the offer stays empty and the request ends with code 403.7.
- Expiration. Keep track of the validity of both the client and the server certificate well in advance — an expired certificate stops the integration overnight.
The procedure for setting up anonymous and Windows authentication is provided in the separate Installing NET Genium on the web server guide.