Photo by Georg Bommeli on Unsplash

Setting Up JWT Authentication in a Rails API (part I)

Vanessa Martinez
4 min readOct 19, 2020

If you want to use signup and login for one of your apps, you should get familiar with at least one of the ways to authenticate your users. This is a short overview of how to set up authentication on the server side using JSON Web Tokens (JWTs). Check out part II for the frontend setup, where I use React.

JWT authentication is great because it gives you the flexibility of authenticating users in a stateless way. That means that a user’s data is encrypted in a token in the form of a JSON object. The user’s data is never stored in a database. Instead, the token is sent along with every authentication request and decrypted in the server. So, let’s see how it all works.

Gems

After setting up your Rails API, which I will not cover here, you need to install some gems:

bundle add jwt && bundle add active_model_serializers

Next, uncomment out rack-cors and bcrypt in your Gemfile. Bundle install once more. Now, uncomment the code in your cors.rb file, and change origins from example.com to *. This is very important—otherwise, you will get a CORS error. Your file should look like this:

However, before deploying your app, you will want to change allowed origins from *, which means “all,” to a more specified origin.

Setting Up Users

After creating your User model with a username and password_digest, you should add has_secure_password, which encrypts your password using ActiveModel, and add validations too:

Then, create a user serializer:

rails g serializer user

Make sure to run rails db:create and rails db:migrate before continuing.

Afterwards, you can start to set up your users controller. The create method below, along with the private user_params, is what enables us to create a user upon signup.

You should also update your user serializer at this point, since you will call upon it in your create method above.

Routes

Next, you can update your routes. You can ignore lines 8–10.

Test Out SignUp

By this point, you should be able to successfully create/signup a new user. Try it before proceeding with the rest of this tutorial. After setting up a controlled form, here’s an example of how I did it in React (Note: We have not encoded a token yet; we’re simply testing the ability to create a user object with username and password):

If you see a new user in your console, please proceed.

Protecting Your App at the Highest Level: Application Controller

So far, we’ve set up the ability for a user to signup, but that doesn’t safeguard your app. You need to lock it down so that users don’t have access to any other part of the app unless they’re signed up, logged in, or staying logged in. Since all controllers inherit from the Application Controller, it’s best to place our “gatekeeper” functionality all the way at the top.

I’ll explain the code below.

The very first thing our app does (line 2) is call on the authorized method (line 42), which checks if the logged_in? method returns truthy. The logged_in? method will check if the current_user method executes successfully. The current_user method will check if the decoded_token method runs OK. If the decoded_token method detected that the auth_header method found an Authorization header, then decoded_token will finish executing, which allows current_user to finish. If any of these methods fail, the authorized method will deny the user access.

Issuing a Token for a User

So what about the encode_token method? That’s actually the method that we need to create a token for a user in the first place. We will use that method in our users controller, so let’s update it now. Refer to line 19 and below. Also, don’t forget to add the skip_before_action (line 2), so our app doesn’t automatically shut down without giving our users the chance to sign in through the create method.

Notice that if our user instance is valid we create a token variable (line 22) and call on the encode_token method and pass in the user’s id. Recall that this method takes in a “payload” for its parameters. That’s because JWTs are made up of 3 parts—3 strings, to be exact—separated by periods:

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyMH0.46frU1AjZSzpt5vX-I9LR6iWQ7jYZzTB8W_TAZkm1qU
  1. The first part is the header.
  2. The second part is the payload (data like our user’s id).
  3. The third part is a hash of the header and the payload, known as the signature. It includes a secret key, which you should ideally hide in a .env file and then list it in gitignore.

Now, for Login

At this point, a user can signup and be issued a token. So, let’s add login functionality. First, we’ll need an auth controller.

rails g controller api/v1/auth

Then, add in this code:

We use skip_before_action (line 2) just like we did in our users controller because we want the app to allow users to login through the create action of our auth controller. Notice that we use the encode_token method for login too. That’s because a user needs a new token each time they fill out the login form. We’ll get to “staying logged in” in part II—how to set up the client side (during which you WON’T need a new JWT).

In the meantime, go ahead and test out what you have so far. You should be able to sign up or login a user.

Sources:

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Vanessa Martinez
Vanessa Martinez

Written by Vanessa Martinez

Freelance Software Engineer. Experience in JavaScript, React.js, and Ruby on Rails.

No responses yet

Write a response