TLS certificates specifying hosts via their CommonName field is more or less gone
TLS certificates for hosts and domains must somehow identify what hostname (or names) they're for. Historically there have been two ways to do this. The first way was a specific sub-field, the CN or CommonName, of the certificate's overall Subject Name. This had the problem that it could only have one name. When people started wanting to have TLS certificates that covered more than one name, they invented another mechanism, the Subject Alternative Name (SAN) extension.
As a practical matter, all vaguely modern software that wants to properly validate TLS certificates has supported (and often preferred) Subject Alternative Names for some time. A great many TLS certificates in the wild are for multiple hosts and it's generally unlikely that the host you're connecting to is the one name that the system chose to put in the CN field; software that only supports CN cannot validate those TLS certificates. As a matter of timing, SANs have been theoretically mandatory since 2002 and checking only SANs has been theoretically required since 2011 (which means that since 2011 or earlier, the CN was supposed to always be one of the SANs).
These days, any remaining support for looking at TLS certificate CommonName to validate TLS certificates is getting more and more extinct (and more so than I expected when I started writing this entry). In the browser realm, Chrome apparently turned it off in 58, released in 2017, and then threw out the option to check it again in Chrome 65 (from the comment on my old entry, which was ironically written shortly before Chrome did this). Firefox is said to have removed support in version 48, from August of 2016. Safari apparently stopped looking at CommonName in iOS 13 and macOS 10.15, which I believe date from late 2019. This Go change also talks about how browsers removed it in 2019 ('last year' for a mid 2020 change).
In non-browser TLS code, Go started ignoring CN by default in Go 1.15 (released in August of 2020) and this will be the only option starting in Go 1.17 (to be released in August of 2021), per here. Since Firefox doesn't support CN any more, I assume that NSS doesn't either, since NSS is basically Firefox's underlying TLS implementation. I have no idea what other TLS libraries are doing, but I would expect that many of them will support CommonName for some time to come; TLS libraries are historically behind browser practices. Hopefully they are all following the 2011 requirement to check only SANs when SANs are present (which they should always be in public certificates).
Probably TLS certificates will continue to contain CommonName fields for a long time to come. Having a Subject Name in general is common (although apparently not actually required) and the CN is a standard (although not required) part of the Subject Name, so you might as well throw it in. Even Mozilla and Let's Encrypt (still) have TLS certificates with CNs. However, since I checked this now, the current CA/Browser Forum baseline requirements (version 1.7.3) allow but don't require CommonName (section 220.127.116.11.2, which says that it's 'discouraged, but not prohibited'). Given how conservative most Certificate Authorities are, I expect them to be issuing TLS certificates with CommonName fields until they're required to stop.
(An interested party could scan Certificate Transparency logs to see if there were very many issued certificates without CNs. Probably there are some; someone must have tried it out at some point through an official CA.)
PS: no-common-name.badssl.com has a TLS certificate without a CN, or at least it's supposed to (via), but the TLS certificate is expired right now as I write this entry so it's hard to test how client software behaves. See also, which pointed me to no-subject.labs.vu.nl, which has a currently valid TLS certificate with no Subject Name at all.
When browsers (or at least Firefox) send HTTP Basic Authentication headers
We're long term fans of using HTTP Basic Authentication in Apache, but while I know how to configure it in Apache
(and even how to log out of it in Firefox),
I haven't really looked into some of the finer details of how it
works. In particular, until recently I hadn't looked into when the
browser (or at least Firefox) sends the
header in HTTP(S) requests and when it doesn't.
The simple story of how HTTP Basic Authentication (also)
works is that when your browser requests a URL protected by Basic
Authentication, Apache will answer with a HTTP 401 status and some
additional headers. If your browser has relevant credentials cached,
it will re-issue the HTTP request with an
added. If your browser doesn't have the credentials, it will prompt
you for login information (in a process that's recently been
improved) and then re-issue the request.
Of course this simple story would be rather bad for responsiveness,
since it implies that the browser would make two HTTP requests for
every URL protected by HTTP Basic Authentication (one without any
authorization, which would get a 401, and then a retry with
authorization). So browsers don't do that. Instead to some degree
they treat the
Authorization header like a cookie and
preemptively send it along for at least some requests to your
website. The question I was curious about was how broadly Firefox
did that. Unfortunately for us, the answer is that Firefox doesn't send
Authorization header very broadly.
(This is an appropriate choice for security, of course.)
As far as I can tell from some simple experimentation, Firefox will
Authorization for any URL under a directory
on your site where it's been challenged for HTTP Basic Authentication
before (in the same Basic Authentication realm and so on). It won't
Authorization outside of the hierarchy under
those directories. That's kind of abstract, so here's a concrete
Suppose I have a website with URLs (among others) of:
All of these URLs other than the /statics/ hierarchy are protected by the same HTTP Basic Authentication, configured once for /grafana/ and everything underneath it and once for /alertmanager/ (and everything underneath it).
If I request the /grafana/d/overview/ dashboard in a clean session,
I will get a 401 and then have to authenticate. If I then request
the /grafana/d/pingstatus/ dashboard, Firefox will not preemptively
Authorization, because it's not in or under the first
URL; instead it will get a 401 and then re-send the request. If I
go to /grafana/ (the top level) Firefox will get a 401 again, but
now if I go on to /grafana/d/downhosts/, Firefox will preemptively
Authorization because it's under a URL that Firefox has
been challenged on.
(If /grafana/d/overview was a page instead of a directory,
requesting /grafana/d/pingstatus afterward would preemptively send
Authorization header because they would both be under the
If I request /alertmanager/ or /statics/ after all of this, my
Firefox won't send a preemptive
Authorization because both
of them are outside of /grafana/. Requesting /alertmanager/ without
authentication will get a 401 and Firefox will resend the request
Authorization header, but Firefox will never request
/statics/ with an
Authorization header. The /statics/ URL
is outside of all HTTP Basic authentication directories and the web
server itself will never reply with a 401 to trigger Firefox's
(If you want to think of it in cookie terms, I believe this is what would happen if the web server set a cookie with a Path= of the initial URL directory and then could add more paths as you clicked around the site.)
In HTTP, the server's HTTP 401 reply to the browser contains no
(reliable) information that the browser can use to determine what
URL hierarchy is covered by authentication. The HTTP server has no
way of telling the browser 'this challenge is for all of /grafana/'
(even though Apache knows that); it just gives 401s for all of those
URLs when Firefox sends requests without an
header. Eventually Firefox hopefully learns all of the URLs that
need Basic Authentication that you (and Grafana) are actually using.