A more detailed article on this topic can be found here: https://www.nopio.com/blog/authentication-authorization-rails/
If you have followed through the previous article, then we should now have a basic API for our Books. Since our website now has functions, we should add authentication features so users can sign up and login. This can help us track users and implement authorization later on.
Let’s generate some components needed for this:
rails generate devise:install
Generate the views for the authentication pages:
rails g devise:views
Devise is the gem (plugin/library for rails) that has a bunch of pre-built functions we can use to implement authentication.
We can now run the follow to generate the User model for our database:
rails generate devise User
You should now have a basic login screen for the website! To check, restart your rails server and visit http://localhost:3000/users/sign_in
Click on Sign up and create a user
After you create the user, you should be automatically signed in. Or you can sign in through /users/sign_in. If you are already signed in, it will just take you to the home page. Now we just need a way to let users know that they are signed in.
Let’s add a navigation bar at the top of the page for User options like signing in and signing out. Go to /app/views/layouts/ and open up your application’s layout file: application.html.erb. Then change the contents so that it looks like this: https://gist.github.com/mt9304/d2bb86ad1b3e50f28bf4a14b4f344c3b
Now, we can add some CSS to style the page just a bit. Open up /app/assets/stylesheets/ and rename the application.css to application.scss. Then edit the contents in there to include bootstrap and add some styling: https://gist.github.com/mt9304/e9087f054ee8fb773f0180caeb75ab5c
The @import bootstrap line lets us use a very popular css library. More information on Bootstrap here: http://getbootstrap.com/
It essentially has a bunch of pre-built styles we can use to make a website so we don’t have to style it from scratch.
Checking if logged in
Let’s make it so that you will only see the Login button if you are not already signed in. Similarly, the Logout button should only appear if the user is already signed in. To do this, let’s open up the /app/views/layouts/application.html.erb file again and make some changes to the user menu section. (around lined 32):
<% if user_signed_in? %>
<%= link_to "Edit profile", edit_user_registration_path %>
<% else %>
<%= link_to "Sign up", new_user_registration_path %>
<%= link_to "Login", new_user_session_path %>
<% end %>
<% if user_signed_in? %>
<%= link_to "Logout", destroy_user_session_path, method: :delete %>
<% end %>
Your application.html.erb file should now look something like this: https://gist.github.com/mt9304/3a87440097d5de9e16ef40c704270528
In Ruby on Rails, the .html part of the file name shows it is an HTML file, and the erb extension at the end let’s the server know that this can accept Ruby code as well. The parts in between the angle bracket/percentage signs (<% some_code %>) are to indicate Ruby code, which is usually programming logic that HTML files would otherwise not be able to use. The brackets without ‘=’ signs like <% some_code %> are indicators of Ruby code that do not need to render anything, while the ‘=’ signs like <%= some_code %> indicates that something should be rendered. In this case, we can see that the “if else” logic of checking a user’s authentication does not need rendering, while the actual links to the Login/Logout functions need rendering, since they are actual buttons on the page.
The code that says something like link_to and new_user_session_path are just pre-built functions to make it more convenient (it also looks more readable, since it spells out exactly what it does). The Login line of code <%= link_to “Login”, new_user_session_path %> is essentially just an ‘a’ tag with the href value of /users/sign_in.
When you login now, you should be able to see the Logout button, and the Sign in button would no longer be there. This allows users to see if they are logged in or out. Now if you ever want content that only users who are logged in should see, you know to just wrap it with these one of these lines: <% if user_signed_in? %> Yay, you are logged in!<% end %>
This is how the login page should look like now:
In the next article, we will go through Authorization, which means giving different users certain roles (such as Admin or Client) and allowing each of these roles to see different content.