REST Architecture – Issues with Treating Client Session as Resource/Application State

api-designArchitecturehateoasrestsession

Given these example REST API / HATEOAS applications:

  1. InfoQ How to GET a Cup of Coffee example
  2. Java Spring REST API example

… where POST/PUT/PATCHING resources clearly alters the state/availability of (other) resources — for example in:

  1. (REST example API 1)

    PUT /order/1234 HTTP/1.1
    ...
    
    <order>
    ...
      <status>preparing</status>
    ...
    </order>
    

    … alters the state of the order, such that certain order options are not available anymore;

  2. (REST example API 2)

    PUT /games/1/doors/3 HTTP/1.1
    ...
    
    {"status": "OPEN"}
    

    … alters the state of the game, such that certain game options are not available anymore

— what would be wrong with treating a client session as a resource/an application state as well?

Consider this example, to see what I mean:

Let's imagine API key 1234 is the owner of /products/1 and only this API key is allowed to operate on/view this product.

Request:

GET /products/1 HTTP/1.1

Response:

HTTP/1.1 403 Forbidden

Request:

POST /sessions HTTP/1.1
Authorization: NiceAPI apikey=1234

<session>
  <apiKey>1234</apiKey>
</session>

Response:

HTTP/1.1 201 Created
Location: /sessions/2ef4c...

// created session sent along for convenience
<session>
  <hash>2ef4c...</hash>
  <apiKey>1234</apiKey>
</session>

In response to Richard Tingle's comment, the above response could be adjusted to send a cookie, in stead of the hash in the session resource representation:

HTTP/1.1 201 Created
Set-Cookie: session=2ef4c...; Secure; HttpOnly
Location: /sessions/2ef4c...

<session>
  <hash>2ef4c...</hash> // not necessary/desirable anymore
  <apiKey>1234</apiKey>
</session>

… to bind the session resource to a client


Request:

GET /products/1 HTTP/1.1
X-Session: 2ef4c... // or a Cookie header, etc.

Response: (if server verified session resource exists)

HTTP/1.1 200 OK
// product content

Request:

DELETE /sessions/2ef4c... HTTP/1.1
Authorization: NiceAPI apikey=1234

Response: (if server verified session belonged to the API key)

HTTP/1.1 204 No Content
// session resource successfully deleted

Request:

GET /products/1 HTTP/1.1

Response:

HTTP/1.1 403 Forbidden

I mean, in both earlier mentioned REST API / HATEOAS applications the operations valid for any particular resource was dependent on other resource states and/or earlier client actions, as well (e.g. it's part of the application logic).

Given that client state/session management is generally frowned upon when talking about REST, how are the earlier mentioned REST API / HATEOAS application states different than my proposed session as a resource/application state?

Best Answer

what would be wrong with treating a client session as a resource/an application state as well?

There is nothing wrong with that per say, the problem comes when you try and use application state (in the form of session resources) as a form of authentication.

You are basically saying that if the application is in this specific state then this client (say client X) is authenticated to access this resource. You have turned your resource state into an authentication system.

Roy Fielding lists the reasons not to do this.

https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#fig_5_3

  • The authentication part of the system doesn't have to be aware of the current application state to authenticate a request. You could authenticate a request on a completely different server, or the same authentication could be used in different parts of the system without having to know resource state.

  • The system is more reliable. Imagine that the update to the session resource failed for some reason, or was updated by something else after the client got a session key. Is the user logged in? When the client tries to update the products resource the server rejects this, but the client doesn't know why. It must remember that previously it tried to log in via a session, go back and try that again. It then has to figure out from that resource why it can't get a session. Anyone has used a web site that uses sessions can testify how confusing it gets, all of a sudden a request can just fail and the site dumps you back out to the login page, even though there was nothing wrong with the request. Imagine now trying to parse what happened automatically via code.

  • The system scales better. Without the application having to track resources in relation to each other it allows the system to scale out. Yes updating a resource might have side effects (if I delete this resource, also delete this resource), but those are specific to the domain logic. It isn't something like if I create this session resource tell EVERY one of these resources that for the next 10 minutes this user can access them. That is a lot more application state to remember and vastly limits scalability and caching.

Like a lot of advantages of REST these benefits only become apparent at a larger scale than one client talking to one web server. Scale beyond that and you will very quickly be cursing sessions.