views:

232

answers:

7

I'm developing a new experimental web-application framework, and I decided to give RESTful some attention. I've read up on the basics, and feel like I have a pretty good understanding of RESTful as a concept.

I've got a system up and running, using URLs strictly to define 'nouns' in the system and take the 'verbs' from the HTTP request methods. I'm using javascript ajax calls to provide access to the DELETE and PUT methods which HTML forms cannot provide. (I realize these measures aren't strictly required to be RESTful, but it satisfies the 'Uniform Interface' requirement).

The problem comes with stateless-ness and cacheability with authentication. The standard model for user authentication on websites involves a "login" authentication event, after which (if successful) a user is "inside the wall" with a persistent secure session and may see and do things on subsequent requests which unauthenticated users may not. This persistence of authentication seems to break RESTful-ness. Caching and statelessness appear to be broken, because the authenticated user will probably see HTML which is different from that which a non-authenticated user will see for the same request (for instance, there might be a login form in a sidebar for the logged-out user).

Using www-authenticate strategies to authenticate a user only on the requests which require authentication seems to be a step in the right direction, as it doesn't involve the concept of a persistent secure session. However there's still the question of how to portray a "logged in" appearance to the end user in keeping with what we've all come to expect from websites.

So in the current thinking, what's the preferred way to handle authentication and permissioning of a webpage in a strictly RESTful way, while still allowing for logged-in decorations in the HTML?

+1  A: 

I think about it like this: The "noun" in user authentication is a session. So your login form uses a POST request to "create" a new session, and logging out uses a DELETE request to "delete" the session.

I know what you mean about the persistence of authentication going against RESTfulness, but the cookies (which give the illusion of persistence) are simply a part of each request.

Alex Reisner
I agree with the noun being the session, as I indicated in my answer. You may also consider using the PUT verb when logging out, which will simply 'expire' the session instead of deleting it, especially if you are logging session history inside a database. DELETE is also good however.
Daniel Vassallo
A: 

If your RESTful framework is only going to be used by your web application, and will not be used as an API for third parties, I see no reason why you cannot use the same authentication scheme as the rest of your application. You could think of this authentication as a lower-level layer than the "application" level. The application level may still remain stateless in a pure RESTful way.

Of course if you are planning to create a RESTful web API, you will need to give this more thought.

Justin Ethier
+2  A: 

This persistence of authentication seems to break RESTful-ness

Instead of authenticating a user, you may think about creating a session. You will be returned a new "Session ID", along with the appropriate HTTP status code (200: OK, 403: Forbidden, etc).

The user will probably see HTML which is different from that which a non-authenticated user will see for the same request

You will be asking your REST server: "Can you GET me the HTML (or any resource) for this Session ID?". The HTML will be different based on the "Session ID".

With this method, there is no wall for "persistent secure sessions". You are simply acting on a session.

The noun (or the resource) would represent the the actual session, if you opt for this method.

Daniel Vassallo
Hmm, so for example unauthenticated users might see the URL: www.whatever.com/Articles/some_titlewhere authenticated users might be directed to: www.whatever.com/Session/12345/Articles/some_titleAnd a 307 redirect can bounce users from one to the other when appropriate.I can go along with that. There's the slight organizational imperfection of these nouns basically being the same thing in two different locations, but I can live with that.
Jonathan Hanson
+3  A: 

"The standard model for user authentication on websites involves a "login" authentication event, after which (if successful) a user is "inside the wall" with a persistent secure session"

  1. This isn't really correct. It's partly true, but only for web sites that invent their own authentication.

  2. If you use "digest authentication" the browser must send the credentials with each request.

Digest authentication -- credentials with each request -- is totally RESTful.

Do that.

To make things slightly more streamlined, you can compute the digest authentication Nonce based on time so that it's good for some period of time (6 minutes, 0.1 hr is good). Everyone few minutes a request will send a 401 status and require recomputation of the digest.

S.Lott
I've already implemented digest authentication, and I agree it meets the RESTful requirements. But you generally do not want to show "delete" and "edit" buttons to users that may not perform those actions. We've come to expect that websites will show us only what we may do. This is what I meant by "Logged-in decorations in the html" at the end of my question.
Jonathan Hanson
The HTML form is presented (generally) in response to a GET. The GET is authenticated; the form that comes back is based on the authentication; not any sort of "session".
S.Lott
S.Lott - This is a good point. I was wrestling with this philosophy for a while, and I think you're right: the user credentials submitted via digest-auth can be seen as just another parameter on the GET request, and therefore it's ok to respond with html that's been customized for individual users. The only minor issue I'd quibble over is that cacheability is complex in this scenario, though I guess I could always consider the requirement for issuing a 304 Found as "has the requested resource changed since the last time THIS USER requested it".
Jonathan Hanson
+1  A: 

One option to preserve cachability in intermediaries for pages with user-specific elements is to add the user-specific markup via Ajax. You serve every use the same page, including some JavaScript that will do an XHR request to a resource that returns something different based on the user login. You then merge this into the page on the client side. The major part of the page will then be cachable as it's the same for every user.

Another option is to use ESI (Edge Side Includes). With these, the cache itself can merge different representations to build up the final result.

Stefan Tilkov
Funny you should mention that, i was playing around with fetching page elements via ajax as a solution. I think this may ultimately be the way I go, if it works out.
Jonathan Hanson
+1  A: 

"This persistence of authentication seems to break RESTful-ness. Caching and statelessness appear to be broken, because the authenticated user will probably see HTML which is different from that which a non-authenticated user will see for the same request"

It is ok if the representation of the resource is slightly different based on the authentication information. The auth information is part of the message and therefore the message is still "self-descriptive". Conceptually you are still accessing the same resource, and the edit and delete links are allowed transitions, not additional pieces of data. Controlling what transitions are available based on who accesses the resource seems valid to me.

Darrel Miller
A: 

Re: Daniel's answer:

If a session is a transient object that gets quickly deleted, this is not very cachable, as any cache you create would only have a useful lifetime of maybe a day, but also continue to use up space in the cache anyway.

Wouldn't it be better to create the USER as an object, and authenticate using the digest authentication, (or a cookie if you must). that way, each user gets their own persistant cache instead of a cache that lasts a day and disappears.

This also makes more logical sense to me, since you're making a page look different depending on the USER, (adding 'hello [name]' and such) and the difference between the "logged in" and "logged out" states depends on whether the user is included in the URL. Whether a particular person is granted access to that user specific url depends on whether they can authenticate as that user.

Breton