Log in with JWT Authentication in Rails and React

Alex Duterte
Sep 20, 2020 · 5 min read

What is JWT? JWT stands for JSON Web Token.

Why JWT? JWT defines a compact and self-contained way for securely transmitting information between parties as a JSON object. An example of what you can use it for is Authorization.

Today I’m going to go through how to setup a log in using JWT with a Ruby on Rails back end and a React front end.

The back end

Application Controller

We’ll need 3 methods here. A secret_key, encode, and decode method.

secret_key

def secret_key
"anything" #a string of your choosing
end

we’ll be using this inside the encode method

encode

def encode(payload)
JWT.encode(payload, secret_key, 'HS256')
end

In the encode method, we are passing in a payload. We then encode the payload, the secret key, and we are using the ‘HS256’ algorithm.

decode

def decode(token)
JWT.decode(token, "anything", true, {algorithm: 'HS256'})[0]
end

The decode method takes in a token. Note that the secret key here is actually the string you used, and NOT the secret_key method. JWT.decode will return an array which is why we have the [0] at the end.

The login

login and token_authenticate methods
Routes. Note the post and get requests.

When the user logs in from the front end, we find the user by what ever param you‘re checking for.

What to take note of here is the lines:

payload = {user_id: user.id}
token = encode(payload)

We want our payload to be unique to that user. No user should ever have the same id so its a safe bet that the payload that will be encoded will be unique.

The token is the result of encoding the payload. We will be sending the user object, and this encoded token to the front end.

token_authenticate

The way this will work might make more sense when we get to the front end. But essentially what is happening is when the user refreshes the page, normally they would be logged out. Since we are using JWT we can “stay logged in” on reload of the page.

In the log in method, we sent the token to the front end. That token is stored in the browser’s local storage. When the page is refreshed, the front end sends the token from local storage and tries to find the user based on the token that was stored.

token = request.header["Authenticate"]
user = User.find(decode(token)["user_id"])

The token is sent to the back end through headers. (We’ll see this on the front end section). Then we find the user by decoding the token.

Front End

On the front end, when the user first logs in, we send a fetch request to the back end.

If we look back at the login method on the backend, we sent back an object of {token: token, user: user}

So when we get our response, we need to take our token that we received and store it in local storage. To do this we write:

localStorage.setItem("token", data.token)
// remember data is {token: token, user: user}

We also set the user to data.user. In this example code, i’m using Recoil.js. But you could use the useState hook, this.state in a class component, or writing to the Redux store.

For more information on useState and Recoil I have articles I wrote here:

Moving on from the shameless self promotion.

So at this point, the user can log in, receive their token and and store it in local storage. If they refresh the page they will still have to log in. Thats not what we wanted!

Authenticating the token

So here I have this useEffect hook acting as a componentDidMount lifecycle method living in my App.js component. If the page is refreshed, it will check the local storage for the token. If a token exists, it will send a get request to /login.

get "/login", to: "users#token_authenticate"
#i put my method in the users controller.

But it’s a get request. How do we send data to the backend through a get request?

If you notice, we sent the fetch request with headers.

headers: {"Authenticate": localStorage.token}

In the back end we had

token = request.headers["Authenticate"]

We passed the token through the headers! Pretty Nifty.

So now, the backend checks to find a user based on that decoded token and sends that user object back to the frontend.

The user now essentially stays logged in even if the page refreshes. But also at this point, if the user logs out, he’s still logged in! We’re almost there.

The logout

Right now the token is still stored in local storage. All we have to do is clear the token when the user logs out.

I have setUser({}) because i am using Routes with some conditional rendering. If the user object is empty, it routes the app to a log in page.

Summary

So the flow of what just happened is,

  1. On a successful log in, the backend will encode a token and find a user and send it to the front end.
  2. The front end stores the token into local storage
  3. If the the page is reloaded, the app will send a request to the back end to authenticate the token stored in local storage. If it is authenticated, it will send back the user object back to the front end.
  4. Logging out will clear the local storage token from the browser.

Analytics Vidhya

Analytics Vidhya is a community of Analytics and Data…

Sign up for Analytics Vidhya News Bytes

By Analytics Vidhya

Latest news from Analytics Vidhya on our Hackathons and some of our best articles! Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Alex Duterte

Written by

Fullstack Software Engineer

Analytics Vidhya

Analytics Vidhya is a community of Analytics and Data Science professionals. We are building the next-gen data science ecosystem https://www.analyticsvidhya.com

Alex Duterte

Written by

Fullstack Software Engineer

Analytics Vidhya

Analytics Vidhya is a community of Analytics and Data Science professionals. We are building the next-gen data science ecosystem https://www.analyticsvidhya.com

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store