Skip to content

Brute force protection

Ben Koshy edited this page Feb 4, 2021 · 25 revisions

In this tutorial we will build upon the app created at Simple Password Authentication so make sure you understand it.

First Add some db fields:

rails g sorcery:install brute_force_protection --only-submodules

Which will create:

class SorceryBruteForceProtection < ActiveRecord::Migration
  def self.up
    add_column :users, :failed_logins_count, :integer, :default => 0
    add_column :users, :lock_expires_at, :datetime, :default => nil
    add_column :users, :unlock_token, :string, :default => nil
  end
    
  def self.down
    remove_column :users, :lock_expires_at
    remove_column :users, :failed_logins_count
    remove_column :users, :unlock_token
  end
end
rake db:migrate

Then add the brute_force_protection submodule:

# config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [:brute_force_protection, blabla, blablu, ...]

Refer to your config/initializers/sorcery.rb file to customize specifics that are required - it will not work properly without customization:

# config/initializers/sorcery.rb

user.consecutive_login_retries_amount_limit = 50 
user.login_lock_time_period = (60 * 5) # in seconds

# You'll also need to specify a mailer, a mailer action and a view so that password unlock instructions are sent.
user.unlock_token_mailer = User

# default mailer action is: send_unlock_token_email - but is configurable

You will also need to configure your sessions_controller.rb or equivalent file to register that an incorrect login has occurred which will increase the failed_logins_count on the relevant user model:

# sessions_controller
def create
  login(params[:email], params[:password], params[:remember]) do |user, failure|      
    if user 
    else
      case failure
      when :invalid_password
        user.register_failed_login!
      when :locked
        ...
     end
  end
end

Now please configure your Mailer

# UserMailer.rb
def send_unlock_token_email(user_id)
    @user = User.find(user_id)
    # @url  = # add unlock account url
    mail(:to => @user.email,
         :subject => "Please unlock your account",
         :from => "#{@user.email}"
         )
  end

Clone this wiki locally