How to Create User Authentication in a Ruby on Rails API
Tags: beginners, ruby, webdev
Published: 2020-10-19 03:14:19

##Introduction
Ruby on Rails, for many years now, has been an extremely popular and influential framework that allows a developer to quickly and cost-effectively build and deploy fully functioning backends. With that in mind, in nearly every complex web application the problem of user authentication will most definitely come into play. This guide will attempt to explain how you can quickly build secure authentication for your web application with Ruby on Rails.

##Installation
Make sure the below items are installed on your machine before we begin.
* [Ruby](https://www.ruby-lang.org/en/documentation/installation/)
* [Ruby On Rails] (http://installrails.com/)

##Creating our project
Just like how we would normally create any Ruby on Rails project, we are going to run `rails new <name of project> --api`. We are then going to need to change a few things in the gem file. Within the file "Gemfile" on line 17 there should be a commented line which reads `gem 'bcrypt', '~> 3.1.7'` or something similar. Un-comment it out and add the line `gem 'jwt'` below as well. It should then end up looking something like this.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/54y9rjwx0mrvy3g4hxt9.PNG)
After both are added run the command `bundle install` to add both the gems to your project.

##Creating our User model
Next, we are going to create our user model in which we are going to be using to authenticate. From our terminal, we are going to run `rails g scaffold User username:uniq password:digest`. It is important to note that the digest at the end of `password:digest` means that the user's password will not be stored as plain text within our database and adds a few extra goodies to our project. After our model has completed we are going to migrate our database using the command `rails db:migrate`. After our migration we need to add the lines `validates :email, presence: true, uniqueness: true` to the user.rb file within our models folder. This makes sure that when a new user is created that the username is unique within the database. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/f132x839g8gncz8td3a6.PNG)

##Application Controller
We are now going to create our Authenticate method from within our application controller file so any of our other controllers can access it when needed. Creating an empty method, our file should look like this.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/n0vu57j2mbtj2ym3irsz.PNG)

The first thing we are going to check within our method is whether authorization headers were sent. To do that we can create a small if statement.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/esjfx0nicktferquxxrg.PNG)

After we check whether the auth header was sent, we can then begin to decode our JWT token that should have been sent within the auth header. We should wrap the next few things within a begin rescue block of code which works similarly to a try-catch in other languages. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/oa6mnpx2lc0x894tep6u.PNG)

Within our begin/ rescue block, we should then decode our JWT token, find our payload, and get our user_id so we can then find our User within our database. To do this we will create a method named secret and token.

Our secret method will find a key within a secret key base which we can access like so.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mgukwfpb9h6mt7eo966e.PNG)

We can then create our Token method which will access the second item within the auth_headers array.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jvo1edejcrjl8ka0g82u.PNG)

Afterward, those two methods are created we can finish our Authorize method. All we need to do is get the user_id from our payload and then use that to find our authorized user. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8mfylfyh2xawt3ct4wzx.PNG)

For future application, we are going to add one last method to our application_controller which will be our create_token method.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ytufuzilihfspz9g4fdb.PNG)

The last thing we need within our Application controller class, for now, is to specify ours before action. All we are going to say here is that before anything else is attempted within our application controller we must authenticate first. to do that all we need to do is add `before_action :authenticate`

In the end, our application_controller.rb file should look like this.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/binrifu9tsh6hvt936mj.PNG)

##User Controller

Since our authentication controller is finished we will also want to make a change to our User controller. Specifically, we need to create a token whenever a new user is created. To do this we can use the create_token method we had made earlier within our create method like so. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0qibkp1kkok5izg4a5cz.PNG)

##Authentication Controller

For someone who is not creating a user for the first time, we need to create a login method. We will do this in a controller called AUthentication Controller. To create this controller rin `rails g controller authentication`. A new file should then exist with your controller folder name authentication_controller.rb. Within this file, there should only be an empty class named AuthenticationController.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/d63so6l9bytesn33kc1w.PNG)

Within here we will then create our login method and make sure that it skips our authenticate method we had created earlier.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zl5axa29zerxzw8i3j42.PNG)

Within our method, we must first find our specific user using ruby's find_by method and then authenticate that user once found with our authenticate method we had created in our application_controller.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1vy4t003vil5qskhovpk.PNG)

After we authenticate our user. We can then use the methods we had created earlier within our application controller to make a new JWT token for the user and also send all of the user data as JSON with the render method.

In the end, our authentication_controller.rb file should look like so.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rh4k0a4l018tbftqgmub.PNG)

##Routes

The final step before we are finished with our fully functioning user authentication is to specify our login route. From within routs.rb which is located within the config controller, add `  post 'login', to: 'authentication#login'` which should send any /login request directly to our login method. The file should end up looking something like this.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/w59hywrqb1htbmioxuvl.PNG)