Authentication is something that almost all web applications need to deal with.
But it can seem a bit intimidating for newbie programmers because authentication and security is not something you want to get wrong.
A lot of tutorials recommend that you use a gem such as Devise. Devise is great, but it’s pretty overwhelming when you are still getting to grips with Rails.
Authentication is such a common requirement of web applications, Rails actually has a solution right out of the box.
In today’s tutorial I will show you how Rails makes it incredibly easy to authenticate users with very little code.
Generating the User model
Before we can write the tests for this functionality, first we need to ask Rails to generate what we need:
bin/rails g model User username:string, email:string, password_digest:string
Here I’m generating a
User model with three properties.
This will also generate the following migration:
class CreateUsers < ActiveRecord::Migration def change create_table :users do |t| t.string :email, index: true, null: false t.string :username, index: true, null: false t.string :password_digest, null: false t.timestamps null: false end end end
As will last week’s tutorial (TDD Active Record Models with MiniTest), I’m also going to add some database specific tweaks to ensure the
username fields are unique and that all three fields are required.
Writing the test
Next I can write the test to ensure that a user can be authenticated successfully:
def test_user_should_be_authenticable user = users(:philip) assert(user.authenticate('password')) end
Here I’m grabbing the
:philip user from the fixtures and then asserting that when I call the
authenticate method with a value of
password the method should return
If you run this test now you should see it fail.
Making the test pass
The first thing we need to do to make this test pass is to ensure we have the
bcrypt gem installed. Open up your
Gemfile and make sure the following line is not commented out:
gem 'bcrypt', '~> 3.1.7'
If that line is commented out, simply uncomment it and then run the following command in terminal:
Next we need to create the fixture user that we grab in the test. Open up your
users.yml file under the
fixtures directory and replace the contents with your own user:
philip: email: email@example.com username: test password_digest: <%= BCrypt::Password.create("password", cost: 4) %>
This will generate the user for us and make it available for the test. Notice how I’m using the
BCrypt::Password class to generate the hashed password.
Finally we can add the following to the
class User < ActiveRecord::Base has_secure_password end
This will magically make the authentication functionality from our test work. You can read more about what’s actually going on under the covers in the Rails Documentation
Now if you run that test again, you should see it pass!
As you can see, we didn’t really have to do much to make authentication possible in a Rails application.
Devise offers you a lot of functionality out of the box for quickly building a web application with all of the bells and whistles.
But it’s often better to go back to basics so you can better understands what’s going on at a more granular level.
Rails makes it really easy to accept and store user passwords and then authenticate them as part of your application.
This is typically a fundamental part of a web application, but it isn’t unique, and so it’s better to follow the best practices of Rails rather than trying to roll your own solution!