Skip to content

Using Bcrypt for authentication

leucos edited this page Oct 14, 2012 · 2 revisions

You probably know how to use Authentication in your application already. It only takes a few lines of code to secure your password handling. Using BCrypt is a good way to improve password security on your site.

First, by using BCrypt, you don't store passwords in clear anymore. If your database gets stolen, the passwords are can't be recovered. Also, by using BCrypt hashing, you need a certain amount of CPU power to compute hashes, and you can adjust the level of computing needed, to match hardware performance increase. This makes your application less vulnerable to brute force attacks.

This being said, it's quite straightforward to set-up, so there's no reason to go without BCrypt.

Add bcrypt-ruby to you Gemfile (or install it).

Let's assume your users table has email and password_hash fields.

class User < Sequel::Model
  # Mix in BCrypt module
  include BCrypt
  
  def password
    # Initialize a BCrypt::Password instance from hashed password
    @password ||= Password.new(password_hash)
  end

  # This creates a hashed password from a clear text password
  # The hashed password is then stored in the password_hash member
  # that will be written to the database
  def password=(new_password)
    @password = Password.create(new_password)
    self.password_hash = @password
  end

  def self.authenticate(creds)
    # creds Hash should contain email and password keys
    # Let's check we have eveything
    if !creds['email'] or !creds['password']
      Ramaze::Log.info("Login failure : no credentials")
      return false
    end

    # Ok, get the matching user from the database
    user = self[:email => creds['email']]

    # No user ? Bail out.
    if user.nil? 
      Ramaze::Log.info("Login failure : wrong password")
      return false
    end

    # Real authentication stuff is here
    # This uses the #password method above
    # and Bcrypt::Password#== method for comparison
    if user.password == creds['password']
      Ramaze::Log.info("Login success for %s" % user.email)
      return user
    end
  end
end

This should do the trick. The BCrypt documentation for the ruby gem is really nice and very easy to follow, even for non crypto nerds, and gives more options (especially regarding computing cost adjustment).

Clone this wiki locally