1

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?

  • 1
    I think the point is you could take your session token and put it into another computer and the API wouldn't care. Hence the API itself is stateless; where you're calling it from doesn't matter – Richard Tingle Jun 3 '16 at 15:47
  • @RichardTingle Fair enough. In that case I will alter the application logic to send a Set-Cookie: session=2ef4c...; Secure; HttpOnly header along with the 201 Created in stead of sending along <hash>2ef4c...</hash> in the session resource. Would that be acceptable? – Decent Dabbler Jun 3 '16 at 15:57
  • What do you mean by "acceptable?" Try to pose your questions in a way that is not subjective. – Robert Harvey Jun 3 '16 at 16:02
  • @RobertHarvey Yeah, sorry, when I wrote the comment that question sounded too subjective to me as well, but I couldn't think of more objective way to phrase it. How about this: given that above example REST APIs / HATEAOS applications keep application state, can my suggested adjustments still be considered a part of application state, as well? – Decent Dabbler Jun 3 '16 at 16:09
2

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.

  • 1
    To me, your answer most clearly formulates why utilizing client sessions are generally considered bad practice in REST / HATEOAS architectures. Thank you. – Decent Dabbler Jun 8 '16 at 15:58
  • What is the alternative if you have created a web app and you need to send basic auth with each request? Where/how do you store the credentials safely so you don't have to ask the user for credentials on each request? – Amber Oct 29 '18 at 22:00
2

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

The short answer is that you get unexpected side effects when the client's understanding of application state and the server's understanding of application don't match.

Review Fielding: Section 6.3.4.2.

Notice that, in the examples that you describe, the protocol is changing the state of the resource, not the state of the application.

Longer answer.

There's a really good discussion of application state on stack overflow: https://stackoverflow.com/questions/3105296/if-rest-applications-are-supposed-to-be-stateless-how-do-you-manage-sessions

Clarifications:

Application logic is needed to evaluate the content of the resource to determine what further adjustments (if any) are allowed to be made to the order.

No; domain logic is needed to evaluate if the change proposed by the message from the client should be allowed.

Fielding (2008)

Don’t confuse application state (the state of the user’s application of computing to a given task) with resource state (the state of the world as exposed by a given service). They are not the same thing.

If REST / HATEOAS would only be about changing resource state (which HATEOAS certainly shouldn't, given the AS part of the acronym) then wouldn't they simply be glorified CRUD data warehouse architectures, without any business logic

I'm not quite sure where you are going with that question, but I'm guessing you could use a dose of Jim Webber

HTTP is an application protocol... but it's not your application protocol.

That may help with your concerns about CRUD.

  • Concerning the browser back button: couldn't I just issue a Vary: Cookie header to mitigate caching? And doesn't this back button caching issue also not hold for any other previous application state and its resource representations when the state of a resource has since evolved (as you described in your blog post)? If the barista (of example 1) is preparing our order, but we haven't refreshed /order/1234 yet while we went somewhere else in the meantime and then go back in history, our order representation isn't valid anymore either. In both cases you need caching mitigation mechanisms, no? – Decent Dabbler Jun 4 '16 at 11:47
  • Concerning the application state of the examples: sorry, let me clarify. In example 1: if the barista is preparing the order, no additional items can be added to the order. Application logic is needed to evaluate the content of the resource to determine what further adjustments (if any) are allowed to be made to the order. But perhaps a more convincing example of application state here would be if the payment resource (/payment/order/1234) was created: the state of that resource also restricts any further actions allowed on the order resource. – Decent Dabbler Jun 4 '16 at 11:49
  • In example 2: The state of a door resource determines the state of the game resource. If a door is opened, the game resource state changes, plus you wouldn't be able to open another door resource anymore either. You'd probably get a IllegalTransitionException, resulting in a 409 Conflict status, or something similar. If REST / HATEOAS would only be about changing resource state (which HATEOAS certainly shouldn't, given the AS part of the acronym) then wouldn't they simply be glorified CRUD data warehouse architectures, without any business logic? – Decent Dabbler Jun 4 '16 at 11:50
1

Sessions are temporary data needed by an application, and are usually orthogonal to what the API is doing. Adding session management in the API distracts from the core functionality, and could introduce unrelated bugs.

The best place for session data is in the application itself. However, there's nothing to say that you couldn't make a separate API to manage session data.

One similar example is when you use a token service (OAuth/Open ID Connect) for your auth (Authentication and Authorization). These things are easy to get wrong. Managing these in your API is not ideal when products exist to do this for you. So instead, your API does what it knows and defers questions about resources it does not manage to the owning API.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.