Subject Alternative Names
The Subject Alternative Name extension lists every hostname, IP address or other identity a certificate is valid for. It is the **only** field browsers use for hostname matching — Chrome stopped consulting the Common Name in version 58, and every other current browser followed. A certificate whose CN is `example.com` but which has no SAN extension is rejected with `ERR_CERT_COMMON_NAME_INVALID`, even when the CN matches the hostname exactly. Every name must be listed as a SAN, including the one in the CN.
Why the Common Name stopped mattering #
The Common Name is a free-text field in the subject distinguished name. It was never designed to hold a hostname — RFC 2818 deprecated that use in 2000 — but for years it was what implementations checked.
Chrome 58 stopped consulting it entirely in 2017, and the other browsers followed. Today the matching rule is simple: if the hostname is not in the SAN extension, the certificate does not cover it.
openssl x509 -in certificate.crt -noout -ext subjectAltName Expected output
X509v3 Subject Alternative Name: DNS:example.com, DNS:www.example.com
If that prints nothing, the certificate will fail in every current browser regardless of what the CN says.
The types you can put in a SAN #
| Prefix | Holds | Notes |
|---|---|---|
DNS: |
A hostname | The one you almost always want |
IP: |
An IPv4 or IPv6 address | Public CAs will not issue for private ranges |
email: |
An address | S/MIME and client certificates |
URI: |
A URI | Service identity in some systems |
otherName: |
Anything else | Used by SPIFFE and similar |
Adding SANs to a CSR #
openssl req -new -newkey rsa:2048 -nodes \
-keyout example.com.key -out example.com.csr \
-subj "/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com,DNS:api.example.com" For OpenSSL 1.0.2, which has no -addext, use a config file — see
generate a CSR with SANs.
Wildcards #
openssl req -new -newkey rsa:2048 -nodes \
-keyout wildcard.key -out wildcard.csr \
-subj "/CN=*.example.com" \
-addext "subjectAltName=DNS:*.example.com,DNS:example.com" A wildcard replaces exactly one label, in the leftmost position:
| Certificate SAN | Matches | Does not match |
|---|---|---|
*.example.com |
www.example.com, api.example.com |
example.com, a.b.example.com |
example.com |
example.com |
www.example.com |
*.a.example.com |
x.a.example.com |
a.example.com, x.y.a.example.com |
That first row is why the apex is listed alongside the wildcard in the command above.
Checking a live server #
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -ext subjectAltName The error you get when it is wrong #
ERR_CERT_COMMON_NAME_INVALID in Chrome, or
SSL: certificate subject name does not match target host name from curl. Both mean the same thing:
the hostname requested is not in the SAN list. Check what is there and reissue with the missing name
included.
Frequently asked questions
- Do I still need to set a Common Name?
- Set it, because most public CAs still require one and will reject a CSR without it. Do not rely on it — it plays no part in hostname matching and is best thought of as a label.
- Does a wildcard SAN cover the apex domain?
- No.
*.example.commatcheswww.example.combut notexample.comitself, and nota.b.example.comeither — a wildcard matches exactly one label. List the apex separately when you need both. - Can a SAN contain an IP address?
- Yes, with the
IP:prefix. Public CAs will not issue for private ranges, so in practice this is only useful for an internal CA or a self-signed certificate. - How many names can one certificate cover?
- Public CAs typically cap it around 100. An internal CA has no practical limit. Bear in mind every name is published to Certificate Transparency logs, so a certificate covering many internal hostnames publishes that list.
References
- RFC 6125: service identity in TLS — why the common name stopped being authoritative for hostnames
- RFC 5280: X.509 and CRL profile — the specification every field on a certificate comes from