Assuming you already have a Devise model named User
and you want to add following Devise Security Extension to it:
- Password Expirable
- Password Archivable
- Session Limitable
Add devise-security (https://github.com/devise-security/devise-security) gem to Gemfile:
gem 'devise-security', '~> 0.12.0'
and run
web_app$ bundle install
Note: version 0.12.0 of the gem gives a lot of error in my case. Downgrading gem version fixed the problems:
-
uninstall the gem (ok for RVM):
bundle exec gem uninstall devise-security
-
change the gemfile:
gem 'devise-security', '~> 0.11.1'
-
run bundler:
web_app$ bundle install
Run the generator:
web_app$ rails generate devise_security:install
The generator adds optional configurations to config/initializers/devise-security.rb
.
Enable the modules you wish to use in the initializer.
For example to enable password expiration set the proper time interval in the config.expire_password_after
parameter:
# config/initializers/devise-security.rb
Devise.setup do |config|
# ==> Security Extension
# Configure security extension for devise
# Should the password expire (e.g 3.months)
# config.expire_password_after = false
config.expire_password_after = 6.months
# Need 1 char of A-Z, a-z and 0-9
# config.password_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/
# How many passwords to keep in archive
# config.password_archiving_count = 5
# Deny old password (true, false, count)
# config.deny_old_passwords = true
# enable email validation for :secure_validatable. (true, false, validation_options)
# dependency: need an email validator like rails_email_validator
# config.email_validation = true
# captcha integration for recover form
# config.captcha_for_recover = true
# captcha integration for sign up form
# config.captcha_for_sign_up = true
# captcha integration for sign in form
# config.captcha_for_sign_in = true
# captcha integration for unlock form
# config.captcha_for_unlock = true
# captcha integration for confirmation form
# config.captcha_for_confirmation = true
# Time period for account expiry from last_activity_at
# config.expire_after = 90.days
end
Now add Devise Security modules on top of Devise modules to any of your Devise models:
devise :password_expirable, :secure_validatable, :password_archivable, :session_limitable, :expirable
for :secure_validatable
you need to add:
gem 'rails_email_validator'
Example:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :timeoutable,
:password_expirable, :password_archivable, :session_limitable # Devise Security Extensions
...
https://github.com/devise-security/devise-security#schema
https://gist.github.com/jiggneshhgohel/52bcd562e937ec4dad7b
web_app$ rails g migration AddDeviseSecurityExtensionPasswordExpirableColumnsToUsers
Open the generated migration and add the following code:
class AddDeviseSecurityExtensionPasswordExpirableColumnsToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :password_changed_at, :datetime
add_index :users, :password_changed_at
end
end
web_app$ rails g migration AddDeviseSecurityExtensionSessionLimitableColumnsToUsers
Open the generated migration and add the following code:
class AddDeviseSecurityExtensionSessionLimitableColumnsToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :unique_session_id, :string, limit: 20
end
end
web_app$ rails g migration CreateDeviseSecurityExtensionPasswordArchivableOldPasswordsTable
Open the generated migration and add the following code:
class CreateDeviseSecurityExtensionPasswordArchivableOldPasswordsTable < ActiveRecord::Migration[5.0]
def change
create_table :old_passwords do |t|
t.string :encrypted_password, :null => false
t.string :password_salt
t.string :password_archivable_type, :null => false
t.integer :password_archivable_id, :null => false
t.datetime :created_at
end
add_index :old_passwords, [:password_archivable_type, :password_archivable_id], :name => :index_password_archivable
end
end
web_app$ rake db:migrate
If you need to customize the Password Renewal view, create the file show.html.haml
under /views/devise/password_expired/
.
Example content:
# /views/devise/password_expired/show.html.haml
- content_for :breadcrumbs, t('.password_expired')
%h1= t('.renew_your_passord')
%h2= t('.password_expired')
.row
.col-md-4.col-md-offset-4
.cvForm
= form_for(resource, :as => resource_name, :url => [resource_name, :password_expired], :html => { :method => :put }) do |f|
%h4= t('.renew_your_password')
= devise_error_messages!
.form-group
= f.label :current_password, t('.current_password')
= f.password_field :current_password, autofocus: true, class: 'form-control'
.form-group
= f.label :password, t('.new_password')
= f.password_field :password, class: 'form-control'
.form-group
= f.label :password_confirmation, t('.confirm_new_password')
= f.password_field :password_confirmation, class: 'form-control'
= f.submit t('.change_my_password'), class: 'btn btn-default btn-lg'
.row.top-spaced.center
= back_button root_path, t(:work_with_us_home)
The devise_secutiry generator authomatically creates the ready to use language files:
config\locales\devise.security_extension.it.yml
config\locales\devise.security_extension.en.yml
config\locales\devise.security_extension.de.yml
To translate the password expired/renew password view, add the following rows to the devise translation files in /config/locales/
:
# /config/locales/devise.it.yml
it:
devise:
password_expired:
show:
password_expired: Password scaduta
renew_your_passord: Rinnova la tua password
current_password: Password corrente
new_password: Nuova password
confirm_new_password: Conferma nuova password
change_my_password: Cambia la mia password
# /config/locales/devise.en.yml
en:
devise:
password_expired:
show:
password_expired: Password expired
renew_your_passord: Renew your password
current_password: Current password
new_password: New password
confirm_new_password: Confirm new password
change_my_password: Change my password
devise-security gem version 0.11.1 requires devise < 5.0, >= 4.2.0. Newer versions of devise require ruby > 2.2.1 and rails > 4.2.5.1.
The following is the combination of changes with the minumun impact on older rails apps:
- ruby-2.3.1
- gem 'rails', '5.0.2'
- gem 'devise', '~> 4.2.1'
- gem 'devise-security', '~> 0.11.1'
To update the gems, delete Gemfile.lock and run bundle install
.
thank you very much!!!!!