How to increase the security of your application with JSON Web Tokens — JWT (Rails and React)
Welcome back to this series of posts where I explain the solution I came out with to insert a timer in the JWT, increasing the security in my Rails — React app.
The idea is making a token that will expire in a certain amount of time, so if the user leaves the application or forgets to logoff, we will log him off, increasing the security of our app.
If you want to check or review the first part before jump on this one:
Last thing we did was send the token with a user_id and a issued_date inside of it, now we get this from the server and store it in our browser, in the localStorage variable. The fetch request will return a promise, so we can use the .then block to set the user:
The whole method is now:
Here we get the response from the server, parse it into JSON with res.json(). Since this also returns a promise, we use another .then block to insert this parsed response in the localStorage with the setItem() method.
So now, the token we sent from the server lives in the client browser and, if u refresh or leave the application, the token will still be there.
But that still do not login the user just because the token is in the browser.
What do we have to do to keep the user logged in if we refresh the page?
The process is, when the user refreshes the page (the app mounts) we check if the user has any token in the browser, and make a request to validate the token:
I’m using functional components, so we have to use the useEffect hook (don’t forget to import it in your component) with an empty dependency (empty array), which is equivalent to componentDidMount in class components.
When the component mounts for the first time, we check if the user has a token, if we find one, we call the validateToken method:
This method is just a fetch request, sending the token in the header, under the Authorization key.
The request is sent to the base URL/validate, which will hit this route in the server:
This goes to auth controller, calling the validate method:
The method token_with_user_id_and_time we already know, but where is current_user coming from?
Remember to login the user, we skip before action the method authorized? This time we don’t. So before everything in auth controller we are running it in Application Controller:
Authorized need the helper method logged_in:
The logged_in method uses a helper method “current_user”, that uses another helper method “decoded_token”. We will see the decoded_token in the next part, here, is important to know that current_user gets the user id we put in the token and find the correspondent user for that id in our database. Then, logged_in will convert the output of current_user in true or false (converting it using the double bang (!!) operation ).
So, basically the authorized method says:
- If there is NO a current user, blocks everything and sends the message: “Not logged in or Token expired, Please login!”
- If there’s a user logged in, than we go to auth controller and run the validate method we wanted, issuing a new token and sending to the client.
In the next part of this journey, I will explain the decoded_token method and all of it’s helper methods. After that, it will all connect and make more sense!
Hope you are enjoying and see you next week!