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 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.
|
|