# devise-argon2 [![Gem Version](https://badge.fury.io/rb/devise-argon2.svg)](https://badge.fury.io/rb/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](https://github.com/technion/ruby-argon2) is used, which provides FFI bindings to the [Argon 2 reference implementation](https://github.com/P-H-C/phc-winner-argon2). `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](https://github.com/P-H-C/phc-winner-argon2#library) 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 if `argon2_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 1. Update your `Gemfile` to use `devise-argon2` version 2: `gem 'devise-argon2', '~> 2.0'` 1. Remove `devise-encryptable` from your `Gemfile` 1. Run `bundle install` 1. Remove the line `config.encryptor = :argon2` from `config/initializers/devise.rb` 1. Change your Devise model by removing `:encryptable` and adding `:argon2, argon2_options: { migrate_from_devise_argon2_v1: true }` 1. 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: 1. Remove the `argon2_options { migrated_from_devise_argon2_v1: true }` line from your Devise model 1. 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 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. 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.