Posts Tagged ‘rest’

Web Authentication as it SHOULD have been

Thursday, December 31st, 2009

auth_small

REST is not an easy concept to grasp but once you get it you finally see the light on many different things. Having just read RESTful Web Services, i wanted to point out some unusual revelation that came to me: form based authentication with its login/session/logout workflow, which is currently dominant on the web, is hopelessly broken.
First two words about REST. It’s a set of constraints, of simplifying assumptions which, if applied to an architecture, will guarantee a number of good properties such as simplicity, scalability and reliability. The best known implementation of a RESTful architecture is the web and its backbone protocol, HTTP. HTTP RESTfulness made it good and yet so easy to implement that it eventually emerged as the great darwinian winner. Either your router or a pretty rabbit, if it’s networked it’s likely to speak HTTP.
Instead of giving yet another list of REST rules, i am going to give you a feeling of how the web works from a REST perspective. There’s a server which keeps state of the application, split into meaningful resources. Each resource has its own name (URI). That’s all the server knows. Then there’s a client which acts as a finite state machine visiting resources and then moving to other ones through links and forms. The state of the conversation, the session, where the client have been and where it is now, it’s something the client is in full control of. Server knows nothing about it. That’s statelessness.

Having recently read RESTful Web Services, i wanted to write about the most interesting of my REST-induced epiphanies:

Form based authentication with its login/session/logout workflow, which is currently dominant on the web, is hopelessly broken.

To understand why, one has to grasp how the greatest living RESTful implementation, the web and its backbone protocol HTTP, was meant to work. In a nutshell, there’s a server that keeps the state of the web application, split into meaningful resources. Each resource has its own name (URI) and a set of available representations of itself. That’s all the server knows. Then there’s a client that acts as a finite state machine visiting resources, getting representations and then moving to other resources through links and forms. The state of the conversation, the session, where a client has been and where it is now, is something that belongs to the client. Server drives the client by feeding him a graph made of states and links to other states, but it’s the client who is in charge of following a path. That’s statelessness, the simplifying property that made the web triumph as a darwinian winner.

In this view, authentication should have been largely a client-side business.
The client visits resources anonymously. If it wants to be authenticated, it just starts sending authentication data with each further request. If it wants to be anonymous again, it just stops. It could as well send a mix of authenticated and anonymous requests.
The server doesn’t care of what happens between requests. If a single request carries authentication data, it checks the data and possibly replies as if the client were authenticated. If a request has no authentication data, a generic response is returned. There’s no server-side login through a form, there’s no server-side logout, and above all, there’s no temporal ordering between those two and hence no server tracked session. All of a sudden, the beauty of this comes with great force. By delegating authentication to the browser using the standard HTTP mechanism we can greatly simplify application code.

Unfortunately, in reality this is not the case. During its race to the top, HTTP lost part of its original vision, mainly due to implementation mistakes.

  1. The specs failed to hit the sweet spot of authentication security. They standardized Basic Authentication which, by sending user and password in plain text, scared people to death and Digest which, due to its complexity and required server cooperation, never really caught on. A client-side mechanism with cheap yet reasonable security such as WSSE UsernameToken, later adopted by atom, would have been optimal.
  2. Browsers took away login from client’s hands by showing the popup dialog to input user/password only after a 401 http error code from server. There should have been an always visible “login” button since the specs said “A user agent that wishes to authenticate itself with an origin server–usually, but not necessarily, after receiving a 401…”.
  3. Browsers practically took away logout from client’s hands by requiring to close the browser in order to clean the passwords cache. There should have been an always visible “logout” button.
  4. Browsers gave no chance to customize the ugly and annoyingly modal login dialog. HTML and/or CSS could have been used.
  5. Browsers gave no client-side storage needed to keep session data but again turned back to server with cookies. They should have given something like upcoming HTML5 localStorage and sessionStorage.

Now there’s not much that can be done short of a collaborative effort by all browser vendors. Meanwhile we can keep dealing with authentication in application code on the server, in a never ending pile of custom solutions, each one slightly different, for yet another pretty standard problem. A problem solved 15 years ago.