Authenticating Users in Ruby on Rails

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  
[/bash]  
Here I’m generating a `User` model with three properties.

This will also generate the following migration:  
```ruby  
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.

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 true.

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:

bundle install  
[/bash]

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:  
```ruby  
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!

Conclusion

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!