Damian Mamla Damian Mamla
Technologies

Authentication and Authorization in Rails Tutorial

   Back to list

You create an online web application and you want to define its access policy for the resources which you wish to protect? Or maybe you want to verify the identity of users visiting your website? In this tutorial, I will show you how simple it is to authenticate and authorizate your application using the popular rails gems: Devise, CanCanCan, and Rolify.

What is authentication and authorization?

Authentication is a confirmation of user identity, while authorization determines whether you can access a particular resource.

What is Devise?

Devise is a flexible authentication solution for Rails. It is composed of 10 modules. For example, one module called Trackable, tracks sign in counts, timestamps, and locates IP addresses. Creating a user authentication system is piece of cake when using Devise.

What is Rolify and CanCanCan?

Rolify is Roles library which supporting scope on resource object without any authorization enforcement. CanCanCan is an authorization library which restricts what resources a given user is allowed to access. All permissions are defined in a single location (the Ability class).

Step 1. Create a new Rails application

I used 4.2.6 version of Rails and SQLite as a database. Let’s skip a test and create a new Rails application.

Step 2. Add Bootstrap and styles

Let’s add a ‘bootstrap-sass’ gem to our Gemfile. After cleanups and adding this gem, your Gemfile should look like this:

Then bundle everything:

Now let’s add some styles to our application. First, rename the application.css to the application.scss under the app/assets/stylesheets – in order to use imports. Now add these lines after the manifest:

Secondly, add after 15th list into assets/javascript/application.js file, this line:

Step 3. Edit application.html.erb

In this step, replace content of your views/layouts/application.html.erb file with this:

Step 4. Add flash message

Now add two methods(bootstrap_classs and flash_messages) to app/assets/stylesheets/ApplicationHelper.rb which will be used to display messages.

application_helper.rb

Step 5. Add welcome page

First, create dashboard_controller.rb file under app/controllers folder. Add to this file:

Next, create a dashboard folder under the app/views and create  the index.html.erb file. Let’s make this file looks like this:
index.html.erb

Now you have to open the routes.rb under the config folder. Clear file and add:

Step 6. Start an application

Let’s start our application.
Run this command in your terminal:

Now go to http://localhost:3000 in your browser.
Your application should look like:

 

step6

Step 7. Create a product scaffold

Rails scaffolding is a quick way to generate some of the major pieces of an application.
Let’s create a model, controller, and views for a product in a single operation.

We created a Product which contains name and price.
Remove from app/views/products the below files, as we don’t need them:

_product.json.jbuilder
index.json.jbuilder
show.json.jbuilder

Step 8. Add bootstrap to product files

Now, let’s modify files in app/views/products folder.
form.html.erb
edit.html.erb
new.html.erb
show.html.erb

index.html.erb:

Let’s also clean app/controllers/products_controller.rb to look like this:

And remove from the assets/stylesheets/scaffolds.scss file, this piece of code:

 

Step 9. Add products links to navigation bar

After adding products, we can add products links to the navigation bar. Add this piece of code to app/views/layouts/application.html.erb:

Refresh your browser and go to Products->New, you should see:

step9

Step 10. Add authentication and authorization gems

Let’s move on to the most important thing in this article – authentication and authorization.
First, add these authentication and authorization gems to our Gemfile:

Then bundle everything:

Step 11. Add Devise to the project

We have added Devise to Gemfile, now let’s generate Devise files:

After running this command, some instructions will be displayed on your console.
We only have to do step 1 and 4.
In the first step, ensure you have defined default url options in your environments files. Go to config/environments/development.rb file and add this line:

In the fourth step, we will add Devise views to our app by running:

Finally, create a User model by running:

Restart your app.

Step 12. Check Devise files

Let’s check three of the most important things that were added in previous step.

1) The new model User was created, and it contains the following Devise modules:

2)In the config/routes.rb file, you can see that the new line was added:

If we run the command:

We see the routes that were created for users:

step12

3) All Devise views are located in views/devise folder.

Step 13. Add Bootstrap to Devise

Now add bootstrap to Devise views.
Modify files:
new.html.erb
links.html.erb

devise/registrations/edit.html.erb:

devise/registrations/new.html.erb:

Step 14. Add users links to navigation bar

Let’s add user links to the navigation bar. Add this piece of code to app/views/layouts/application.html.erb:

Reload your browser.

Step 15. Hide links from users that are not logged in

In the top right corner of the navigation bar, we have the Profile tab. When you expand it, you will see more tabs:

step15

Thanks to Devise, we can restrict which tab will be visible for logged and not logged in users. To verify if a user is signed in, we will use the following Devise helper:

Let’s modify the app/views/layouts/application.html.erb file:

Now, let’s reload your browser. After that, you will see that when you expand the Profile tab, only two tabs will be visible (Sign up and Login). It’s because you didn’t log into the application.

To do that, you have to click the Sign up tab, fill out the registration form, and submit it.

step15-signin

If you fill in the form with correct data, you will be logged into the application and will be redirected to the welcome page. Now when you expand the Profile tab, you will see the Edit Profile and Logout tabs instead of the Sign up and Login tabs.

Thanks to Devise, you can now sign in, log in, edit your account, and log out.

Step 16. Restrict access to products

Right now, even users that are not logged in can see, add, edit and remove products. Let’s make sure that only logged in users can add, edit and remove products. We can do this by adding to app/controllers/products_controller.rb this line:

After adding this line of code, reload the browser and check if not logged in user can for example add a new product. If you added the code right, users that are not logged in will will be redirected to the Log in panel and receive the message: “You need to sign in or sign up before continuing.”

step15-access

Step 17. Add a new field to the user

In this step, we will add a username field to the User. First, we have to generate a new migration:

Next, add username to the app/views/registrations/edit.html.erb and app/views/registrations/new.html.erb files:

After that, add to your app/controllers/application_controller.rb file, the following lines:

We have now permited additional parameter username for Devise sign_up and account_update actions.
If you did everything correctly, you can now create a new user containing username.
Reload your browser and go to Sign Up. You should see that the new input called Username is displayed in Sign Up form.

step17

Step 18. Add user to product

Let’s say that we want to know who the product was created by. To achieve that, first we have to add user to the product. Run this comment in your terminal:

After that, modify your app/models/product.rb file, to look like this:

and app/models/user.rb file, to look like this:

Then using the Devise helper method current_user, which returns a current signed-in user, we can add current signed-in user to product. Let’s modify the create action in your app/controllers/products_controller.rb file to look like:

Finally, modify app/views/products/index.html.erb file by adding the Creator column to the table:

Now let’s log into the application and create a new product. After that, go to the product list. In the column Creator, you will see a current user email alongside of the product which you have just now created. For example, when the user [email protected] creates a product which contains the name Keyboard and a price of 120 we get:

step18

 

Step 19. Add Roles

In step 12, we added Rolify to Gemfile. In this step, I will show you how we can use this gem. Let’s say that we want to create two types of users in our application: an admin, a person which will have access to every action in our application, and a client, a person with limited access. To do that, first we have to create Role model and migrate the database:

Finally, remove from app/models/Role.rb file, this line:

Step 20. Populating the Database with seeds.rb

Let’s clean our database by running:

Next, we add some products to the database and create two users, Nicole (admin) and Bruce (client).

Please modify the db/seeds.rb file to look like this:
seeds.rb

and after that, run:

Reload the browser and go to the product list, where you should see something like this:

step20

Step 21. Add CanCanCan to product

In step 12, we added CanCanCan to Gemfile. Let’s now use this gem.
Create the Ability class from CanCanCan:

The Ability class is a place were user permissions are defined. Let’s add two helper methods to app/models/user.rb file:

We will use these methods to check which role users have.

Modify your app/models/ability.rb file to look like:

We defined that the client can perform any action on his own products. The admin can perform any action on all products and the not logged in user can only read (look over) all products.

Next, we have to add this line of code to app/controllers/products_controller.rb file:

This method loads the resource into an instance variable and authorizes it automatically for every action in products_controller.rb. If the user is not able to perform the given action, the CanCan::AccessDenied exception is raised. Let’s customize this exception by catching it and modifying its behavior. Add this piece of code to app/controllers/application_controller.rb:

We catch this exception, set the error message to flash, and redirect to the home page.

Now if you perform an action which a user is not able to perform, for example: remove admin product by client, you should get:

step21

Conclusion

In 21 steps, we created an application which contains simple authentication and authorization.
You can find the source code of the application here: https://github.com/nopio/authentication-and-authorization-tutorial
If you have any questions, feel free to contact us!