If you want users on your web app, you need to be able to authenticate (verify they are who they say they are) and authorize (give the users access to different resources). Thankfully doing this using Rails is a fairly trivial task. In this tutorial we'll go over how to quickly add users and provide authentication on your web site. In Part 2 we'll discuss authorization in Rails.
NOTE: This tutorial assumes some familiarity with the Ruby on Rails framework.
The most basic attributes users require are a username and a password. Sure, you can add email and actual name depending on your needs, but for the sake of simplicity, we're going to keep it simple today. So our first step to adding users to our Rails app will be creating a new db migration and model.
rails g model user username:string password_digest:string
This will give us a new table called users with two columns: username and password_digest. Both of these columns will contain strings. Make sure to run
rails db:migrate after generating your user model.
You might be wondering why we called our password column password_digest and not just password. That is because we will not be storing our users' passwords. That would be a horrible idea for many reasons. Instead, we will be storing a string that is determined by sending our users' password through a complicated algorithm that spits out some garbled text. Although this text is garbled, it is consistently garbled by our rails server, so every time a user signs in, we:
- Receive their password
- Send it through the algorithm
- Compare the garbled output of the algorithm with our stored garbled output (password_digest)
- If they match, boom! The user is authenticated!
We'll go over authentication in more depth in the next tutorial.
We will be taking advantage of the bcrypt gem. Make sure you include this in your Gemfile and check out the GitHub if you want to learn more about the process of garbling a password (hashing and salting).
Thankfully ActiveModel::SecurePassword is included by default with Rails version >= 3. This means less code! Yay! All we have to do to take advantage of the gem is include this line in our user model file.
class User < ApplicationRecord # this is the line I'm talking about has_secure_password # but these lines are probably a good idea too validates :username, uniqueness: true validates :username, presence: true end
We are telling rails to store our users' passwords in their garbled form among other things. The other two lines I included are validations which I'm assuming are fairly intuitive (thanks Ruby & Rails teams) but more here if you are interested: Active Record Validations.
Signing up here means creating a user. Let's create a user!
We will need a controller to tell our application which actions to take depending on where the user is. Let's add a users_controller with this command:
rails g controller users
Now for the body let's add some actions (AKA methods).
class UsersController < ApplicationController # this creates a "blank user instance for our form" def new @user = User.new end def create # create a user instance with the username and password params @user = User.new(user_params) # if it successfully saves to the db if @user.save # send the user to their homepage (show view) redirect_to @user else # if user doesn't save, render the new view render 'new' end end def show set_user end private def set_user @user = User.find_by(id: params[:id]) end def user_params params.require(:user).permit(:username, :password) end end
The next step in the process is adding our front-end signup form. When we ran
rails g controller users, a users directory was created in our views directory. Let's add a file called
new.html.erb. We will need an input field for our user's dream username and another for their password:
<%= form_with(model: @user, local: true, url: '/signup', method: :post) do |f| %> <%= f.text_field :username, placeholder: "username"%> <%= f.password_field :password, placeholder: "password"%> <%= f.submit "Sign Up" %> <% end %>
Again, thanks to Rails, we have access to something to make our markup a little simpler to right -- form helpers! Now our form can take advantage of our model and we can even add error handling soon.
While we're adding this new user view, let's go ahead and add a
show.html.erb, so our user can be greeted once they signup for their new account.
<h1>Welcome <%= @user.username %></h1>
We haven't set up any routes yet so lets go ahead and do that next.
get '/signup', to: 'users#new' post '/signup', to: 'users#create' resources :users, only: [:show]
I've shown a few different ways to add routes here, but you will want to read the Rails docs for routing for more information on good practices and possibilities.
QUICK TIP: You can check out the routes of a rails app by running
Let's go ahead and fire up the rails server with
rails s and head over to
localhost:3000/signup. We should see a form. Go ahead and test it out with a username and password. You should be greeted! Next week we'll go over how to get our application to remember us (sessions) and allow us to access various resources (authorization).