HTTP Basic Authentication and your URL hierarchy

September 21, 2023

We're big fans of Apache's implementation of HTTP Basic Authentication, but we recently discovered that there are some subtle implications of how Basic Authentication can interact with your URL hierarchy within a web application. This is because of when HTTP Basic Authentication is and isn't sent to you, and specifically that browsers don't preemptively send the Authorization when they are moving up your URL hierarchy (well, for the first time). That sounds abstract, so let's give a more concrete example.

Let's suppose you have a web application that allows authenticated people to interact with it at both a high level, with a URL of '/manage/', and at the level of dealing with a specific item, with an URL of say '/manage/frobify/{item}'. You would like a person to frobify some item, so you (automatically) send them email saying 'please visit <url> to frobify {item}'. They visit that URL while not yet authenticated, which causes the web server to return a HTTP 401 and gets their browser to ask them for their login and password on your site (for a specific 'realm', effectively a text label). Their re-request with an Authorization header succeeds, and the person delightedly frobifies their item. At the end of this process, your web application redirects them to '/manage/'. Because this URL is above the URL the person been dealing with, their browser will not preemptively send the Authorization header, and your web server will once again respond with a HTTP 401.

Because this is all part of the same web application, your HTTP Basic Authentication will use the same realm setting for both URLs in your web server and thus your WWW-Authenticate header. In theory the browser can see that it already knows an authentication for this realm and automatically retry with the Authorization header. In practice a browser may not always do this in all circumstances, and may instead stop to ask the person for their login and password again. With this URL design you're at the mercy of the browser to do what you want.

(This can be confusing to the person, especially if (from their perspective) they just pressed a form button that said 'yes, really frobify {item}' and now they're getting challenged again. They may well think that their action failed; after all, successful actions don't usually cause you to get re-challenged for authentication.)

Unfortunately it's hard to see how to get out of this while still having a sensible URL hierarchy, short of never sending people direct links for actions and always having them enter at the top level of your application. One not entirely great option is that when people frobify their items, they are never automatically redirected up; instead they just wind up back on '/manage/frobify/{item}' except that now the page says 'congratulations, you have frobified this item, click here to go to the top level'. This is slightly less convenient (well, if people actually want to go to your '/manage/' page) but won't leave people in doubt about whether or not they really did successfully frobify their item.

When you look at your logs, this behavior may be surprising to you if you've forgotten the complexities of when browsers preemptively send HTTP Basic Authentication information. HTTP Basic Authentication doesn't work like a regular cookie, where you can set it once and then assume it will always come back, which is the model of authentication we're generally most familiar with.

Written on 21 September 2023.
« Restarting nfs-server on a Linux NFS (v3) server isn't transparent
Changing GNU Emacs Lisp functions through advice-add, not brute force »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Sep 21 23:36:10 2023
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.