Saving HTTP Authentication?

December 30, 2003 12:42 AM

Since the web was in its infancy, HTTP has come with a built-in authentication protocol that was simple, if not particularly secure on the wire, supported by all browsers, and almost never used. Even with its security improved by digest authentication, pretty much every major website ignores HTTP Authentication in favour of a form-based approach that is in many ways worse. Why don't we like HTTP Authentication?

  1. Jarring User Interface

    The login dialog, as implemented by web browsers, looks like part of the browser, not part of the site. The only explanatory text is what you can shoehorn into the realm-name, something that field was not intended to do. In addition, it's impossible to present the user with alternatives to logging in while they have the (at least page-modal) login dialog in front of them. You can not give them the option to sign up for a new account or request a password reminder beside the login form.

    All this is just confusing and annoying to the user. Worse, it's ugly: a login form embedded in and styled with the site is orders of magnitude more aesthetically pleasing.

  2. Authentication Is Not Optional

    Either a page requires authentication by returning a 401 response code, or it does not. Many websites, on the other hand, allow users to access pages whether they are logged in or not, controlling instead what content appears on those pages based on login status. Thus, HTTP Authentication is unsuitable.

  3. No Logout

    It's really annoying and fiddly to code a logout option for HTTP Authentication, and you're never really sure the browser will take the hint. Configuring a time-out for idle users is just impossible.

  4. Poor Server Support

    Historically, web– and web-application servers have dealt with HTTP Authentication badly: making it fiddly to configure, hard to plug in alternate providers, and hard to integrate with your applications.

On the other hand, there are certain things that are right about HTTP Authentication

  1. Browser Support

    The browser understands, at the protocol level, how to determine if a page requires authentication, and which credentials to send. Modern browsers give users the option to remember credentials, and seamlessly remain logged into the site between sessions.

    The alternative, as we've all probably had dealings with, involves messing around with user sessions, and putting the user at risk with authentication tokens buried in cross-site-scripting-vulnerable persistent cookies.

    Just as annoyingly, there's the idle timeout problem. We sometimes want to time idle user logins out (for their own safety), but we really have no idea whether the user is idle or not. We've all had that nasty experience of spending a little too long filling out a form, only to lose everything we entered when we find out we've been logged out when it came time to submit it.

  2. Simplicity

    It is far, far easier to build a tool that can perform HTTP Auth, than it is to build one that can navigate the myriad login forms that clutter the web. For example, consider a password-protected RSS feed. It would be easy to write an RSS Newsreader that could retrieve it if HTTP Auth were used, much harder if anything else were put in its place.

My solution is pretty straightforward. Back-port current practice (optional login and in-page login forms) into the standards. First, provide for optional authentication in HTTP:

WWW-Authenticate

The server MAY include a WWW-Authenticate header (as defined in RFC2617) with any successfully retrieved (2xx response code) document. This header denotes that the document was retrieved, but further information may be available if the user authenticates to the realm provided in the header.

On receiving a WWW-Authenticate header with a 2xx response, any user-agent that has credentials cached for the realm SHOULD repeat the request, including those credentials. If the user-agent has no credentials cached for the given realm, it SHOULD NOT interrupt the delivery of the response to the user, but MAY provide some indication that the page accepts authentication, and some mechanism to enter credentials.

As in RFC2617, the user-agent MAY preemptively send the same credentials for any resource located at a URI beneath the one at which the WWW-Authenticate header was received.

Then, provide for HTTP Auth from within web pages.

When a FORM element has a method attribute value of "Auth", this defines a form for providing HTTP Authentication credentials. Its action attribute value is taken to be the name of an HTTP Authentication realm as defined in RFC2617. Authentication forms may contain the following form input elements:

  • username, which will be the username for the login credentials.
  • password, which will be the password for the login credentials.
  • timeout, which will be an optional idle-timeout (in minutes) for the credentials provided in this form.

    The exact definition of idleness is left to the user-agent, but is roughly defined as the amount of time since the user last interacted with a page that required authentication to that particular realm. If timeout is zero, or this field is not provided, the login is assumed to never time out.

On submitting an "Auth" form, the user-agent should cache the credentials for the given realm. If the page on which the form was located was part of that realm and new credentials have been provided, the page should be re-requested with the new credentials. If the page on which the form was located was not part of that realm, it MUST NOT be requested with those credentials, for obvious reasons.

An "Auth" form may also have an optional input element of type logout. User-agents should render this element in the same manner as inputs of type cancel. Selecting this element will cause the user-agent to forget all authentication tokens for the given realm.

Voila. Now all we need is server and tool support, and we're on our way back to a better web.

Update: Zoe points out that the authentication form has appeared before in a 1999 W3C Draft. Which just goes to show that few good ideas are ever original. Shame it was never implemented though.

3 TrackBacks

Listed below are links to blogs that reference this entry: Saving HTTP Authentication?.

TrackBack URL for this entry: http://fishbowl.pastiche.org/mt-tb.cgi/446

On HTTP Authentication from Specialization is for Ants on January 1, 2004 2:21 AM

Charles Miller has a good idea for saving HTTP Authentication.... Read More

Now that I've read what I'm talking about... Read More

Started off with the PHP Security Guide by Chris Shiflett. It openend my eyes to a few topics such as session handling. Also, in the Library I found some good reads as well. For example, on The Fishbowl, I found two articles: Persistent Login Cookie... Read More

10 Comments

Yup. HTTP authentication works much better when the authentication prompt is in a FORM tag -- but Apache may require you to write your own AuthHandler or AuthzHandler to intercept authentication data, as otherwise it appears to like discarding the password.

Do you have any standard reference on the Auth method for forms? HTML 4 seems to define only get and post (http://www.w3.org/TR/html401/interact/forms.html#adef-method). A cursory search on RFC 2617 did not revela any reference to a new form method.

I tried replicating this with PHP and a Mozilla client, and Mozilla won't send the username and password as per RFC2617, but uses the POST method instead.

I'm sorry if I wasn't clear, but the conditional authentication and "Auth" forms methods described in this entry ar just things I thought up last night, and NOT standards that work with any web server or web browser.

Sorry if this caused any conclusions.

Or, indeed, confusion.

That would be nice. Maybe it's time for HTTP 1.2?

Hmmm... this sounds very much like AUTHFORM, doesn't it?

http://www.w3.org/TR/1999/NOTE-authentform-19990203

One problem with current HTTP authentication is the double-request cycle. The browser tries first without auth, and upon receiving a 401, tries again with credentials.

This makes optional authentication a scalability nightmare. If I return a WWW-Authenticate header with a 2xx response, I also am including generated content for an anonymous user. If the browser has credentials to send, then it requests again and I generate content, this time for a known user. For each page. Ick.

I share your frustration, though, and have implemented HTTP auth whenever authentication is mandatory. I'd love to see a simple way to tell the browser to discard it's credentials ("log out") and the "auth" method added to HTML forms. I'm just not sure the optional auth part is going to be a simple extension.

Hans: The current RFCs take account of this. If you authenticate to http://www.example.org/secure, then the browser is allowed to assume that any URL below that (e.g. http://www.example.org/secure/foo) is part of the same realm, and send the authentication without first having to run into the denial.

This would get rid of most of the double-request problem.

Well, the other thing basic auth doesn't help with is where the web server wants to provide the auth details to a particular client.

I'm thinking of central authentication services like CAS and MS Passport in particular. Here, the web server needs to be able to say "okay, you are now logged in as X".

Any ideas how that could work?

Currently, I think you HAVE to use session-based logins...

cheers,

Chris

I have logged a bug against mozilla due to the lack of display of a 401 response uless the user presses the cancel button. Please lobby for this!

https://bugzilla.mozilla.org/show_bug.cgi?id=271383

Previously: Return of the King

Next: Java IDE Feature Request: Per-project file templates