devise-argon2
A ruby gem that gives Devise models which use database_authenticatable
the ability to hash
passwords with Argon2id.
Installation
bundle add devise-argon2
Usage
Add devise :argon2
to your Devise model. For example:
class User < ApplicationRecord
devise :database_authenticatable, :argon2
end
Now the password of a newly created user will be hashed with Argon2id. Existing BCrypt hashes will
continue to work; if the password of a user is hashed with BCrypt, the Argon2id hash will replace
the existing hash as soon as a user signs in (more specifically: as soon as valid_password?
is called with a valid password).
Configuration
Argon2 options
For Argon2 hashing the gem ruby-argon2 is used, which
provides FFI bindings to the
Argon 2 reference implementation.
ruby-argon2
can be configured by passing parameters like profile
, t_cost
, m_cost
, p_cost
,
or secret
to Argon2::Password.new
. These parameters can be set like this:
class User < ApplicationRecord
devise :database_authenticatable,
:argon2,
argon2_options: { t_cost: 3, p_cost: 2 }
end
If the the configured work factors differ from the work factors of the hash in the database, the
password will be re-hashed as soon as valid_password?
is called with a valid password.
Pepper/secret key
The Argon 2 reference implementation has a
built-in pepper which is called secret
. This Argon2 secret key can be set like this:
class User < ApplicationRecord
devise :database_authenticatable,
:argon2,
argon2_options: { secret: ENV['ARGON2_SECRET_KEY'] }
end
Traditionally, peppers in Devise are configured by setting config.pepper
in devise.rb
. This
option in honored but argon2_options[:secret]
takes precedence over config.pepper
. Specifically:
-
config.pepper
is used as secret key for new hashes if and only ifargon2_options[:secret]
is not set. - The verification of existing BCrypt hashes is not touched, so it continues to use
config.pepper
as pepper.
Updating from version 1
With version 2 come two major changes: First, devise-encryptable
is no longer needed. Second, the mechanism for salting
and peppering has changed: Salts are now managed by Argon2 and the pepper is passed as secret key
parameter. If you have existing hashes in your database that have been generated by
devise-argon2 v1, you'll need to set :migrate_from_devise_argon2_v1
in argon2_options
.
With this option your existing hashes will continue to work as the old mechanism for salting and
peppering is used if and only if password_salt
is truthy. The first time you pass a valid
password to valid_password?
, the hash will be updated and password_salt
will be set to nil
.
The next time you call valid_password?
the new salting and peppering mechanism will be used
because password_salt
is not truthy anymore.
As soon as all password_salt
fields are set to nil
, you can delete the column from the database
and remove :migrate_from_devise_argon2_v1
from argon2_options
.
Please note that this works only if your database table has a field password_salt
.
Upgrade Steps
- Update your
Gemfile
to usedevise-argon2
version 2:gem 'devise-argon2', '~> 2.0'
- Remove
devise-encryptable
from yourGemfile
- Run
bundle install
- Remove the line
config.encryptor = :argon2
fromconfig/initializers/devise.rb
- Change your Devise model by removing
:encryptable
and adding:argon2, argon2_options: { migrate_from_devise_argon2_v1: true }
- It should now look something like this
class User < ApplicationRecord
devise :database_authenticatable,
:argon2,
argon2_options: { migrate_from_devise_argon2_v1: true }
end
That's it, you're done! Your users will now be able to log in with their existing passwords and their passwords will be migrated to the V2 format the next time they log in.
Once all of your users' passwords are migrated to the V2 format:
- Remove the
argon2_options { migrated_from_devise_argon2_v1: true }
line from your Devise model - Delete the
password_salt
column from your database using a migration like this:
class RemovePasswordSaltFromUsers < ActiveRecord::Migration[7.1]
def change
remove_column :users, :password_salt, :string
end
end
Note: If you do this before all of your users' passwords are migrated to the V2 format, they will be unable to log in with their current passwords.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
Contributors
Please see here for full list of contributors: https://github.com/erdostom/devise-argon2/graphs/contributors
License
Released under MIT License.