# Client SSL Certificate on Windows: Chrome, Edge, Firefox


<!--more-->

This guide continues the article
[Configuring Client Certificate Authentication on Nginx]({{< relref "client-certificate-authentication-nginx" >}}).
You have a `user1.p12` file with the certificate and private key, and its password. Now it needs to be installed
in the system.

Windows makes this simple: the system has a shared user certificate store (**Personal**), and browsers take client
certificates from it:

- **Chrome, Edge, Opera, Brave, Vivaldi** use only the system store;
- **Firefox** also sees certificates from the system store since version 90, and has its own store as well.

So installing the certificate into the system once makes it available to all browsers.

The certificate goes into the **Current User** store, so administrator rights are not required.


## Installing through the UI

1. Double-click `user1.p12`. The **Certificate Import Wizard** opens.
2. For **Store Location** keep **Current User** and click **Next**.
3. The file path is already filled in; click **Next**.
4. Enter the file password. Import options:
   - **Mark this key as exportable**: leave it unchecked unless the user needs to move the key to other devices.
     This way the private key cannot be exported from the system;
   - **Enable strong private key protection**: optional. Windows will ask for confirmation (or a password) every
     time the key is used.
5. Choose **Automatically select the certificate store based on the type of certificate**; a certificate with a key
   goes to **Personal**.
6. Click **Finish**. You should see **The import was successful**.

The same wizard can be opened from the browser: in Chrome and Edge go to **Settings → Privacy and security →
Security → Manage certificates** (in newer versions, **Manage imported certificates from Windows**) and click
**Import**.

To check installed certificates, open `certmgr.msc` (**Win + R → certmgr.msc**) and go to **Personal →
Certificates**. You can delete a certificate there as well: right-click it and choose **Delete**.


## Installing from the command line

### PowerShell

Enter the password interactively so that it does not end up in the command history:

```powershell
$password = Read-Host -AsSecureString -Prompt "p12 password"
Import-PfxCertificate -FilePath .\user1.p12 -CertStoreLocation Cert:\CurrentUser\My -Password $password
```

By default the private key is imported as non-exportable. Add `-Exportable` to allow export.

List installed certificates:

```powershell
Get-ChildItem Cert:\CurrentUser\My | Format-List Subject, Issuer, Thumbprint, NotAfter
```

Delete a certificate together with its private key:

```powershell
Get-ChildItem Cert:\CurrentUser\My | Where-Object Subject -like "*CN=user1*" | Remove-Item -DeleteKey
```

### certutil

`certutil` is available on every Windows system and works in a regular command prompt. The `-user` switch is
required: without it the certificate goes to the computer store and administrator rights are needed. The tool asks
for the password itself.

```bat
certutil -user -importpfx user1.p12 NoExport
```

List certificates in the **Personal** store:

```bat
certutil -user -store My
```

Delete a certificate by serial number or by the name from the previous command's output:

```bat
certutil -user -delstore My "user1"
```


## Firefox

Since version 90 Firefox automatically uses certificates from the Windows system store. If you installed the
certificate using one of the methods above, nothing else is needed: Firefox will offer it when you open the site.

If Firefox does not see the certificate, open `about:config` and check that `security.osclientcerts.autoload` is
`true`.

You can also install the certificate into Firefox only, without touching the system: **Settings → Privacy & Security
→ Certificates → View Certificates... → Your Certificates → Import...** The certificate will then be available only
in this Firefox profile.


## Selecting the certificate automatically

After each restart the browser asks which certificate to use. If the user has only one, the choice can be automated
with the **AutoSelectCertificateForUrls** policy. For example, for Chrome create a string value in the registry:

```bat
reg add "HKCU\Software\Policies\Google\Chrome\AutoSelectCertificateForUrls" /v 1 /t REG_SZ /d "{\"pattern\":\"https://example.com\",\"filter\":{\"ISSUER\":{\"O\":\"Company Name\"}}}"
```

Put the **Organization Name** of your certificate authority in the filter. For Edge use the
`HKCU\Software\Policies\Microsoft\Edge\AutoSelectCertificateForUrls` key. You can check that the policy is applied on
the `chrome://policy` or `edge://policy` page.


## Troubleshooting

- **The browser does not offer a certificate.** Check in `certmgr.msc` that the certificate is in **Personal** and
  has a private key (a key icon, and "You have a private key that corresponds to this certificate" in its
  properties). If it ended up in **Other People** or **Trusted Root Certification Authorities**, delete it and import
  it again into **Personal**.
- **The wrong certificate was selected.** Chrome and Edge remember the choice until the browser restarts, so close all
  its windows, including background processes in the system tray.
- **The server rejects the certificate.** Check that it is signed by the CA set in `ssl_client_certificate` in the
  nginx configuration, and that the CA and the client have different **Organization Name** fields.

Guides for other systems:
[Linux]({{< relref "client-certificate-linux" >}}),
[macOS]({{< relref "client-certificate-macos" >}}),
[Android and iOS]({{< relref "client-certificate-android-ios" >}}).

