Setting up Bcrypt in your Rails project

setting-up-bcrypt-in-your-rails-project

If you’re here you probably already know that storing passwords in plain text is a bad idea. Here is a step-by-step guide on how to set up Bcrypt in your Rails project. It’s quite simple, yet offers powerful security to your user’s information as well as any sensitive data you might be storing in your database. It’s so simple in fact, you’ll probably have time to read about how it works at the end if you aren’t already familiar.

  1. If you don’t have your Rails project set up go ahead a run:

rails new ProjectName

  1. Add the ‘bcrypt’ Gem to your project’s Gemfile:

gem 'bcrypt', '~> 3.1.13'

In your terminal, run:

bundle install

  1. Generate the model you will be storing the password in and include password_digest as an attribute. Remember the default type when using a generator is a string which is how the password_digest will be stored.

rails g model User name email password_digest

  1. In the model, add your associations and validations and include has_secure_password
class User < ApplicationRecord
     has_secure_password

     # Include additional validations...

end
  1. Migrate your database to create your users table

rails db:migrate

  1. Implement user registration in your users_controller with a create action along with your error handling. Though we included a password_digest attribute in our user table, we will still take in a password and password_confirmation in our user_params. Bcrypt will do the work of hashing the plain text password and storing it as password_digest thanks to that handy single line of code in step 4, has_secure_password.
class UsersController < ApplicationController 

rescue_from ActiveRecord::RecordInvalid, with: :render_record_invalid

     def create 
          user = User.create!(user_params) 
      session[:user_id] = user.id
        # Include any additional successful registration steps
    end

private 

     def user_params 
          params.permit(:name, :email, :password, :password_confirmation) 
     end 

     def render_record_invalid(e)
          render json: {errors: e.record.errors.full_messages}, status: :unprocessable_entity
     end
end

So far the code above will take in new user information as use_params and create a new user. It will verify that the password and password_digest match and save the new user to the database if so along with the Bcrypt generated password_digest. If the password and confirmation do not match, the bang operator in User.create! will raise an error that will be rescued with the render_record_invalid function to return any errors so we can render them to the dom for our user.

  1. Lastly, we will authenticate our users when they sign in. This will go into the controller responsible for your user authentication, such as a sessions_controller. First, the action will find the user via their email, in this example and authenticate the password they input against the store password_digest.
class SessionsController < ApplicationController 
     def create 
    user = User.find_by(email: params[:email]) 
    if user && user.authenticate(params[:password]) 
        # Handle successful login 
    else 
        # Handle login failure 
     end 
  end
end

Thats it! Your passwords are being stored securely.

How it works:

Bcrypt is a hashing algorithm that takes a bit of data (e.g. password) and creates a "digital fingerprint" from it. In other words 'password' becomes something like 2b$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa.

What makes Bcrypt more secure is that it adds "salt" to the password before hashing it. Salt is a random bit of additional data that is prepended to the password the user entered before it is hashed. This looks like turning our password into E4OAovh7rbpassword before processing it through the hashing algorithm. This way, if two people have have the same password, the salt ensures that their password_digest is completely different.

So how do we authenticate the user?

Bcrypt stores the password salt prepended on the password hash in the password_digest so all we have to do is add that salt to the password the user entered upon log in and see if it matches. Yes, the stored hash does have embedded information about its computation. As seen in the example below from the Bcrypt official npm page.

$2b$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
 |  |  |                     |
 |  |  |                     hash-value = K0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
 |  |  |
 |  |  salt = nOUIs5kJ7naTuTFkBy1veu
 |  |
 |  cost-factor => 10 = 2^10 rounds
 |
 hash-algorithm identifier => 2b = BCrypt

Read more about Bcrypt for Ruby here.

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
programmatically-access-working-locations-with-the-calendar-api

Programmatically access working locations with the Calendar API

Next Post
maitriser-le-travail-asynchrone-:-comprendre-son-essence-et-les-strategies-pour-une-mise-en-oeuvre-reussie

Maîtriser le travail asynchrone : Comprendre son essence et les stratégies pour une mise en œuvre réussie

Related Posts