(3) Tue Jul 27 2004 18:15 PST: The "realm" field of HTTP basic auth is a really bad place to put helpful status messages like "Your account has been locked." In fact, it's a really bad place to put anything except the name of the realm (or some other string that never changes). If you try to be clever and put other strings into it depending on state, browsers will think it's two or more totally different types of authentication and in some cases can go into an infinite loop.
Posted by Leonard at Wed Jul 28 2004 10:10
Oh, you're fine. The important thing is that the string can never change during someone's flailing attempts to authenticate. I didn't explain this well enough and I edited the entry to make it more clear.
Here's the scenario I had (this was at work). Users could have their accounts locked for too many authentication failures. If they were logging in through the web form it was no problem to display a message to that effect when they tried to log in. But with basic auth a locked user might try again and again to log in, with the right username and password, and never know why they were being rejected.
So I changed the realm name. If the request you sent didn't have any credentials at all, you got a realm name of "Welcome". If you sent credentials that were valid but for a locked user, or something else weird happened, you still got a 401 but the realm name was something like "Sorry, you're locked" or "You only have 1 more try before you get locked."
Here's where the infinite loop happened. Let's say you initially hit the site and got a "Welcome" 401. You tried to log in to with "foo"/"bar" and got a "Sorry, you're locked" 401. Then you hit enter at the authentication popup (effectively logging in as ""/""). Since you're not providing any credentials, the server gives you another "Welcome" 401.
To us this looks like normal interaction between a person and a server. But to a web browser it looks like a very picky URI that demands authentication two separate times: once to a realm called "Welcome" and once to a realm called "Sorry, you're locked".
When the browser gets a "Sorry, you're locked." 401 in response to "foo"/"bar", it figures "Well, I didn't get a 403, so 'foo/bar' must be okay for the 'Welcome' realm. When it gets a "Welcome' 401 in response to ""/"", it figures "Well, I didn't get a 403, so ''/'' must be okay for the 'Sorry, you're locked' realm."
And this is where it makes its fatal mistake. It looks at the name of the realm and says "I know that one! I just have to authenticate with 'foo'/'bar' and everything will be fine!" Of course doing so just gets a "Sorry, you're locked" 401, but the browser feels it has this under control, because the user already told it how to respond to "Sorry, you're locked": with ""/"".
So it goes back and forth between "foo"/"bar" and ""/"", between "Sorry, you're locked" and "Welcome", always imagining that if it just submits credentials one more time it will finally not get any more of these (to it) Kafkaesque 401s.
There are longer loops (depending on how many distinct messages you can have for the same realm name), but that's the easiest one to describe.
What I should do is just send 403 for locked users. I don't see any way to warn a user about an impending lock, though.