Kim Stacks
Kim Stacks

Reputation: 10822

Why is it not good to use $_SESSION in Restful Implementations?

Original Question:

i read that for RESTful websites. it is not good to use $_SESSION. Why is it not good? how then do i properly authenticate users without looking up database all the time to check for the user's roles?


I read that it is not good to use $_SESSION.

http://www.recessframework.org/page/towards-restful-php-5-basic-tips

I am creating a WEBSITE, not web service in PHP. and i am trying to make it more RESTful. at least in spirit.

right now i am rewriting all the action to use Form tags POST and add in a hidden value called _method which would be "delete" for deleting action and "put" for updating action.

however, i am not sure why it is recommended NOT to use $_SESSION. i would like to know why and what can i do to improve.

To allow easy authorization checking, what i did was to after logging in the user, the username is stored in the $_SESSION.

Everytime the user navigates to a page, the page would check if the username is stored inside $_SESSION and then based on the $_SESSION retrieves all the info including privileges from the database and then evaluates the authorization to access the page based on the info retrieved.

Is the way I am implementing bad? not RESTful? how do i improve performance and security?

Thank you.

Upvotes: 2

Views: 469

Answers (3)

deceze
deceze

Reputation: 522402

As written in the article, this "rule" is utter nonsense. The author is damning $_SESSION, but is perfectly okay with cookies storing authentication information. He goes on to say:

In the event you need more than a cookie’s worth of data fall back to storing it in a central database with the authentication still in the cookie.

What's the difference between storing data in a session with a token in the cookie, and storing data in a database with authentication in the cookie? There is no difference, other than that by using a token, you're not transmitting authentication data, possibly in the clear, with every request.

There is no difference between transmitting additional information with each request and transmitting a token that represents additional data, but needs to be resolved through a session on the server. It's just a matter of security and practicality.

The argument is often that a server should be "stateless". Since RESTfulness pertains to the HTTP protocol though, "statelessness" does not mean "the server doesn't store any state". Statelessness from a protocol's perspective means that I can make any number of requests in arbitrary order, and I receive the same resource for the same request.

GET  /index.html
POST /someaction
GET  /index.html  -> should return the same *resource* as before

Contrast that with a real state-keeping protocol such as FTP:

LS       -> gets list of files in current directory
CD /dir  -> changes directory, i.e. changes state
LS       -> same command gets list of files for a different directory

That's the real difference between a RESTful protocol and a state-keeping protocol. Whether the server stores any data pertaining to the user or not is totally an implementation detail of the server and has nothing to do with RESTfulness. If the server returns the same resource as response to the exact same request, regardless of what other kinds of requests were made in between, it's stateless and thereby RESTful.

This doesn't have anything to do with authentication or storing additional data and also does not preclude that requests or URLs may eventually expire.

If URLs/requests do expire, there's a special way to handle that using HTTP: responding with appropriate status codes. If a user sends a request with an expired token/login, the server is not supposed to answer with a login screen at the requested URL. That would violate RESTfulness.

not RESTful:

GET /restricted/page

200 OK

Please log in here:
Name: _____
Password: _____

----------------------

POST /restricted/page
[name, password]

200 OK

Content of restricted page.

----------------------

GET /restricted/page

200 OK

Content of restricted page.

RESTful:

GET /restricted/page

401 Unauthorized

or

GET /restricted/page

307 Temporary Redirect
Location: /login

----------------------

GET /login

200 OK

----------------------

POST /login
[name, password]

307 Temporary Redirect
Location: /restricted/page

----------------------

GET /restricted/page

200 OK

This does not "replace" the resource /restricted/page as the bad example would do, keeping the server RESTful. It does appropriately signal to the client that the request is valid, just not right now. Note that the term resource is always used, not response. It's okay for the server to respond differently, but it's not okay to offer a different resource (content*) at the same URL. If that was the case, the client would also need to keep track of the current state of a session (like FTP) to be able to tell what's going on. Statelessness is much more about the client being stateless than the server. It doesn't preclude the server from keeping track of what the client is doing.


*) Note that content is not equivalent to resource. It's okay for the content of a resource to change and update.

Further note that there are valid reasons against using $_SESSION, most notably scalability across several servers. Keeping a server RESTful is not a valid reason though. If you need any sort of state, like expiring logins or a shopping basket, you need to keep track of that information somewhere. A server session is as valid a place as a cookie, and is in many cases the better choice. Whether that session is implemented using $_SESSION or a database or pen and paper is an implementation detail.

Upvotes: 8

Remus Rusanu
Remus Rusanu

Reputation: 294407

The very same link you posted offers a solution:

In practice this means storing authentication information in a cookie with a timestamp and a checksum.

But personally I don't agree that a checksum is enough. I prefer the authentication cookie to contain a timestamp, the original login IP (to prevent cookie hijacking) and to be fully encrypted with a site key.

Upvotes: 1

Devin Ceartas
Devin Ceartas

Reputation: 4829

Sessions as they are normally implemented are not RESTful because they store only a small token on the client side, while the actual "state" of the client (logged in, contents of shopping cart, etc) are stored on the server. REST requires the web to follow it's original design of "statelessness" meaning that each request is just the same as any other -- the server doesn't have to keep track of anything.

If all the data is stored in a cookie -- actual data, not just a token -- that can be in keeping with REST. I tend to have the server return all the state to the client as a block of encrypted text, which is decrypted by the server on the next call to confirm the user is logged in, what is in the shopping cart, etc.

Upvotes: 1

Related Questions