Goodbye PHP Sessions, Hello JSON Web Tokens

REST API's are meant to be stateless. What that means is that each request from a client should include all the information needed to process the request. In other words, if you are writing a REST API in PHP then you should not be using $_SESSION to store data about the client's session. But then how do we remember if a client is logged in or anything else about their state? The only possibility is that the client must be tasked with keeping track of the state. How could this ever be done securely? The client can't be trusted!

Enter JSON web tokens. A JSON web token is a bit of JSON, perhaps something that looks like this:

{
"user": "alice",
"email": "test@nospam.com"
}

Of course, we can't just give this to a client and have them give it back to us without some sort of assurance that it hasn't been tampered with. After all, what if they edit the token as follows:

{
"user": "administrator",
"email": "test@nospam.com"
}

The solution to this is that JSON web tokens are signed by the server. If the client tampers with the data then the token's signature will no longer match and an error can be raised.

The JWT PHP class makes this easy to do. For example, to create a token after the client successfully logs in, the following code could be used:

If the token has been tampered with then $token will be empty there will not be an id available. The JWT class makes sure that invalid data is never made available. If the token is tampered with, it will be unusable. Pretty simple stuff!

18 Responses

Add your response

You would still have to compare the $POST['token'] with one on the server. $SESSION could hold this but it's only really good on small projects that dont require load balanced servers. A better solution would be to have a backend cache server like memcache which stores the user_id and any other useful data under a random key which you assign to the token to pass back to the user. The user then posts the key back and the data is fetched from the cache referenced by the key. Although for storing the logged in user, its probably not going to work having the user post the key back each time, but rather for the server to set a cookie.

The server doesn't need to store the token. The server only needs to remember the secret key that the token was signed with. That would be most likely stored in some sort of configuration.php and would not change often.

With an authentication scheme like this, you're not able to invalidate a token once it hat granted. If an intruder obtained a password and logged in, he can use the JWT forever. Setting a TTL in combination with asking the existing password to change the password while somewhat solve the most dire cases, but it's still a rather weak in comparison with invalidating sessions server side.