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
Authorization
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
Authorization
header 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 the
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 preemptively send
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 preemptively send
Authorization
outside of the hierarchy under those directories. That's kind of abstract, so here's a concrete example.
Suppose I have a website with URLs (among others) of:
/grafana/
/grafana/d/overview/
/grafana/d/pingstatus/
/grafana/d/downhosts/
/alertmanager/
/statics/
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 send
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 send
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 a
Authorization
header because they would both be under the /grafana/d/ directory.)
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 with the
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 sending of
Authorization
.
(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
Authorization
header. Eventually Firefox hopefully learns all of the URLs that need Basic Authentication that you (and Grafana) are actually using.