Jan 06, 2016
Table of contents:
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.
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 email
and username
fields are unique and that all three fields are required.
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 true
.
If you run this test now you should see it fail.
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:
bundle install
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: test@test.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 User
class:
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!