# Client SSL Certificate on macOS: Safari, Chrome, 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.

On macOS client certificates are stored in the **Keychain**, and all major browsers use it:

- **Safari, Chrome, Edge, Opera, Brave** take certificates from the keychain;
- **Firefox** also sees keychain certificates since version 90, and has its own store as well.

So installing the certificate into the **login** keychain once makes it available to all browsers.

{{< admonition type=warning open=true >}}
**macOS 14 and earlier do not accept `.p12` files created by OpenSSL 3 with default settings.** OpenSSL 3 encrypts
the container with AES-256 and PBKDF2, which the system can read only since macOS 15. Older versions report a wrong
password even when it is correct. Recreate the file with the `-legacy` option:

```shell
openssl pkcs12 -export -legacy -in user1.crt -inkey user1.key -out user1.p12
```
{{< /admonition >}}


## Installing through the UI

1. Double-click `user1.p12`. **Keychain Access** opens. If it does not, open it with Spotlight
   (**Cmd + Space → Keychain Access**) and choose **File → Import Items...**
2. Select the **login** keychain and click **Add**.
3. Enter the `.p12` password.
4. The certificate appears under **My Certificates**. Expand it; there should be a private key under it.

On the first visit to the site the browser offers to choose a certificate, and macOS asks whether the application may
use the private key: "*Browser* wants to sign using key ... in your keychain". Enter your account password and click
**Always Allow** so the question does not come back.

To delete the certificate, right-click it under **My Certificates** and choose **Delete**. The private key is deleted
with it.


## Installing from the command line

macOS has a built-in `security` tool for working with the keychain. Import into the **login** keychain:

```shell
security import user1.p12 -k ~/Library/Keychains/login.keychain-db
```

The tool asks for the file password in a separate window. In scripts the password can be passed with `-P`; to keep it
out of the shell history, read it first:

```shell
read -s P12PASS
security import user1.p12 -k ~/Library/Keychains/login.keychain-db -P "$P12PASS" \
    -T "/Applications/Safari.app" -T "/Applications/Google Chrome.app"
unset P12PASS
```

The `-T` options allow the listed applications to use the private key right away, so macOS does not ask for
permission on the first visit. Without them you will see the prompt described above.

List installed client certificates (with private keys):

```shell
security find-identity -v -p ssl-client
```

Delete a certificate together with its private key. Use the certificate **Common Name** or its SHA-1 hash from the
previous command's output:

```shell
security delete-identity -c "user1"
```

### Default certificate for a site

If the keychain holds several client certificates, you can set which one to use for a specific site. Safari will then
stop asking:

```shell
security set-identity-preference -c "user1" -s "https://example.com/"
```


## Firefox

Since version 90 Firefox automatically uses certificates from the keychain. 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. The `-legacy` restriction does not apply here: Firefox reads modern `.p12` files on any macOS
version.


## Troubleshooting

- **"Wrong password" on import.** If the password is correct and macOS is older than 15, recreate the `.p12` with the
  `-legacy` option (see above).
- **The browser does not offer a certificate.** Check in **Keychain Access** that the certificate is in the **login**
  keychain under **My Certificates** and has a private key. If it ended up under **Certificates** without a key,
  delete it and import the `.p12` again.
- **The wrong certificate was selected.** Chrome remembers the choice until it restarts, so quit it with **Cmd + Q**.
  For Safari, check the identity preference: in **Keychain Access** it appears as an entry with the site address.
- **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:
[Windows]({{< relref "client-certificate-windows" >}}),
[Linux]({{< relref "client-certificate-linux" >}}),
[Android and iOS]({{< relref "client-certificate-android-ios" >}}).

