Let's assume you want to build an APP with.
- ReactJS
- REST API with PHP
- Using JWT
1. Introduction
You must forget about sessions when building REST API's.
REST API's are meant to be stateless, so they must not depend on sessions, they must process requests with only the data given by the client.
2. Authentication
All the client wants to do is only to exchange some username
& password
for a token.
This is an example HTTP request
POST /api/v1/authentication HTTP/1.1
Host: localhost
Content-Type: application/json
{
"username": "foo",
"password": "bar"
}
And the response is:
{
"token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
3. let's go into more details into request/response
How our API will process the authentication request?
It will check if a user with username foo
& password bar
is founded and it's active in DB
It will generate a JWT (Json Web Token)
It will return response containing the JWT
This is some super simple auth method, just for example.
public function authAction()
{
/** Get your payload somehow */
$request = $_POST;
//Validate if username & password are given/
$user = $this->model->auth($username, $password);
if(!$user) {
//throw error for not valid credentials
}
$jwt = $this->jwt->create($user);
//return response with $jwt
}
As you see they are no sessions set or anything.
How our client side will process the response?
The client could use some package like superagent for handling the requests & responses to our API this way the process will be simplified to this:
let data = {
username: email,
password: password
};
request
.post('/api/v1/authentication')
.set('Content-Type', 'application/json')
.send(data)
.end(function (error, response) {
//response.body.token
});
4. Creating JWT on server side
You could use some 3RD PT package for generating and validating JWT instead of writing it yourself.
Look at this package, you can see how it's done.
And remember to always create strong signatures.
I recommend using RSA keys
I am not advertising or supporting this project, just found it useful to share it here. I had never used it, I'm using something similar to this on my NodeJS projects.
5. Saving JWT on client side
They are two ways as you already know localStorage
& cookies
For me I am using cookies, because:
- They are a bit more secure.
- Expire date can be set without implementing some custom logic.
- Older browser support (very old browsers, so it's not that important).
But it's all up to you.
6. Using JWT
From now on every request to server you must include your JWT.
In your REST API you must write a method to validate the JWT and exchanging it for user object.
Example request:
let jwt = ...; //GET IT FROM LOCALSTORAGE OR COOKIE
request
.get('/api/v1/posts')
.set('Content-Type', 'application/json')
.set('Authorization', jwt)
.end(function (error, response) {
});
How API will process this request
public function postsAction()
{
$jwt = $this->headers->get('Authorization');
if(!$this->jwt->validate($jwt)) {
//throw unauthorized error
}
$user = $this->model->exchangeJWT($jwt);
//Your logic here
}
7. Expire date & cookie
If you are using cookie to save your JWT, be careful with setting the expire dates.
The cookie expire date must be equal to the JWT expire date.