devise-argon2 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d20fef20b04b01fd33fd4e8b7104f50ef57ce75e6a4406df46a3ea10fe693a1
4
- data.tar.gz: 7b66c6a1e646eea75a16c43ae37a95b557e6342488885a73ab60a80d3d5903a5
3
+ metadata.gz: 7542aed226ac27c831a5f6acdbb6011fe8b6632e83a60902341c4f44bad38b27
4
+ data.tar.gz: 63891613bb7343641df64221d56533f646543c8eb0c8b3f9fe32186a4f4c46df
5
5
  SHA512:
6
- metadata.gz: 668de52215782a24691ec1d44ced5c85376d99099da8352c583a3452fb78d60e928fef311efe5bdfadffc5dfac130b1affabf9ce26b0197ea807d5602ed257d8
7
- data.tar.gz: 12669cb6bbd94d3cc6e0427a6bf805152417f47858145daf6fba20907d32c10f9c8bedf4535a7ede8af0c572723886537ee782967e7b9b7e5566ec01c6f6ec27
6
+ metadata.gz: 958d4df9feceff3bb4b28c85eed86f0072cd9914ba7f00cfdc26379def7af570647812fb72e14303b02ad435d4e8450d6cbc63b76a7b23380de1218828fac365
7
+ data.tar.gz: f639d484fe68ff7d39df88511a06c15b4518ddce58cf02057d39f99524aa5942af83427bb2268f66fe2facd36c30cb72477782f903d2d17e1dfd8f7e644a4fc7
@@ -1,35 +1,73 @@
1
1
  name: Test suite
2
2
 
3
- on: [push, pull_request]
3
+ on: [push, pull_request, workflow_dispatch]
4
4
 
5
5
  jobs:
6
6
  test:
7
7
  runs-on: ubuntu-latest
8
8
  strategy:
9
9
  matrix:
10
- ruby-version: ['2.7', '3.0', '3.1', '3.2', 'ruby-head']
11
- rails-version: ['~> 7.0', '~> 6.1']
10
+ ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3']
11
+ rails-version: ['~> 6.1', '~> 7.0', '~> 7.1', '~> 7.2', '8.0.0.beta1']
12
+ argon2-version: ['2.2', '2.3']
12
13
  orm:
13
14
  - adapter: active_record
14
15
  - adapter: mongoid
15
- mongoid-version: 8.1.2
16
+ mongoid-version: 9.0.2
16
17
  - adapter: mongoid
17
- mongoid-version: 8.0.6
18
+ mongoid-version: 8.1.6
19
+ - adapter: mongoid
20
+ mongoid-version: 8.0.8
18
21
  - adapter: mongoid
19
22
  mongoid-version: 7.5.4
20
- include:
21
- - rails-version: '~> 7.1'
23
+ exclude:
24
+ - rails-version: '~> 7.2'
25
+ ruby-version: '2.7'
26
+ - rails-version: '~> 7.2'
27
+ ruby-version: '3.0'
28
+ - rails-version: '8.0.0.beta1'
29
+ ruby-version: '2.7'
30
+ - rails-version: '8.0.0.beta1'
31
+ ruby-version: '3.0'
32
+ - rails-version: '8.0.0.beta1'
22
33
  ruby-version: '3.1'
23
- orm:
24
- adapter: active_record
25
- - rails-version: '~> 7.1'
34
+ - orm:
35
+ adapter: mongoid
36
+ rails-version: '8.0.0.beta1'
37
+ - orm:
38
+ adapter: mongoid
39
+ mongoid-version: 8.0.8
40
+ ruby-version: '3.3'
41
+ - orm:
42
+ adapter: mongoid
43
+ mongoid-version: 8.0.8
44
+ ruby-version: '3.2'
45
+ - orm:
46
+ adapter: mongoid
47
+ mongoid-version: 7.5.4
48
+ ruby-version: '3.3'
49
+ - orm:
50
+ adapter: mongoid
51
+ mongoid-version: 7.5.4
26
52
  ruby-version: '3.2'
27
- orm:
28
- adapter: active_record
53
+ - orm:
54
+ adapter: mongoid
55
+ mongoid-version: 8.0.8
56
+ rails-version: '~> 7.2'
57
+ - orm:
58
+ adapter: mongoid
59
+ mongoid-version: 7.5.4
60
+ rails-version: '~> 7.2'
61
+ - orm:
62
+ adapter: mongoid
63
+ mongoid-version: 7.5.4
64
+ rails-version: '~> 7.1'
29
65
  env:
30
66
  RAILS_VERSION: ${{ matrix.rails-version || '~> 7.0'}}
31
- MONGOID_VERSION: ${{ matrix.orm.mongoid-version || '8.1.2'}}
67
+ MONGOID_VERSION: ${{ matrix.orm.mongoid-version || '8.1.6'}}
32
68
  ORM: ${{ matrix.orm.adapter }}
69
+ ARGON2_VERSION: ${{ matrix.argon2-version }}
70
+ DEVISE_VERSION: ${{ matrix.devise-version || '~> 4.9' }}
33
71
  steps:
34
72
  - uses: actions/checkout@v4
35
73
  - name: Set up Ruby ${{ matrix.ruby-version }}
@@ -37,6 +75,7 @@ jobs:
37
75
  with:
38
76
  ruby-version: ${{ matrix.ruby-version }}
39
77
  bundler-cache: true
78
+ cache-version: 1
40
79
  - uses: supercharge/mongodb-github-action@1.10.0
41
80
  if: ${{ matrix.orm.adapter == 'mongoid' }}
42
81
  - name: Setup rails test environment
data/.gitignore CHANGED
@@ -14,7 +14,7 @@ rdoc
14
14
  spec/reports
15
15
  spec/rails_app/log/*
16
16
  spec/rails_app/tmp/*
17
- spec/rails_app/db/test.sqlite3
17
+ spec/rails_app/db/test.sqlite3*
18
18
  test/tmp
19
19
  test/version_tmp
20
20
  tmp
data/CHANGELOG.md CHANGED
@@ -1,20 +1,40 @@
1
- # Changelog
1
+ # Changelog
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## [2.0.2] - 2024-09-30
6
+
7
+ ### Changed
8
+ - When migrating users from v1 to v2, the `encrypted_password` update will no longer trigger callbacks (ie send email to users)
9
+
10
+ ### Added
11
+ - Tests for newer dependency versions
12
+
13
+ ## [2.0.1] - 2023-10-18
14
+
15
+ ### Added
16
+ - Add Argon2 and devise to the test suite
17
+ - Add @moritzhoeppner as an author
18
+
19
+ ### Fixed
20
+ - Fix work factors implementation
21
+
22
+ ## [2.0.0] - 2023-10-16
23
+
5
24
  ### Added
6
25
  - Expose Argon2 options for configuring hashing work factors
7
26
  - Add support for migration v1 hashes
8
27
  - Add support for migrating bcrypt hashes
9
28
  - Add tests for Mongoid
10
29
  - Add Changelog :)
11
-
30
+
12
31
  ### Changed
13
32
  - Change salting / peppering mechanism
14
33
  - Change CI from Travis to GitHub Actions
15
-
16
- ### Removed
34
+
35
+ ### Removed
17
36
  - Remove `devise-encryptable` dependency
18
37
  - Remove superflous dependency on devise `password_salt` column
19
38
 
39
+ Thank you to @moritzhoeppner for the significant contributions to this release!
20
40
 
data/Gemfile CHANGED
@@ -5,9 +5,16 @@ gemspec
5
5
  gem 'rspec'
6
6
  gem 'simplecov'
7
7
  gem 'activerecord'
8
- gem 'sqlite3'
9
8
  gem 'rails', ENV['RAILS_VERSION'] || '~> 7.0'
9
+ gem 'argon2', ENV['ARGON2_VERSION'] || '~> 2.3'
10
+ gem 'devise', ENV['DEVISE_VERSION'] || '~> 4.9'
10
11
 
11
12
  if ENV['ORM'] == 'mongoid'
12
13
  gem 'mongoid', ENV['MONGOID_VERSION'] || '~> 7.5'
13
14
  end
15
+
16
+ if ENV['RAILS_VERSION'] == '8.0.0.beta1'
17
+ gem 'sqlite3', '~> 2.1'
18
+ else
19
+ gem 'sqlite3', '~> 1.6', '>= 1.6.6'
20
+ end
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # devise-argon2
2
2
  [![Gem Version](https://badge.fury.io/rb/devise-argon2.svg)](https://badge.fury.io/rb/devise-argon2)
3
+ ![](https://github.com/erdostom/devise-argon2/actions/workflows/test.yml/badge.svg)
3
4
 
4
5
  A ruby gem that gives Devise models which use `database_authenticatable` the ability to hash
5
6
  passwords with Argon2id.
@@ -39,7 +40,7 @@ or `secret` to `Argon2::Password.new`. These parameters can be set like this:
39
40
  class User < ApplicationRecord
40
41
  devise :database_authenticatable,
41
42
  :argon2,
42
- argon2_options: { t_cost: 3, p_cost: 2 }
43
+ argon2_options: { t_cost: 3, p_cost: 2 }
43
44
  end
44
45
  ```
45
46
 
@@ -6,7 +6,7 @@ require "devise-argon2/version"
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "devise-argon2"
8
8
  gem.version = Devise::Argon2::ARGON2_VERSION
9
- gem.authors = ["Tamas Erdos"]
9
+ gem.authors = ["Tamas Erdos", "Moritz Höppner"]
10
10
  gem.email = ["tamas at tamaserdos com"]
11
11
  gem.description = %q{Enables Devise to hash passwords with Argon2id}
12
12
  gem.summary = %q{Enables Devise to hash passwords with Argon2id}
@@ -18,8 +18,8 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
- gem.add_dependency 'devise', '>= 2.1.0'
22
- gem.add_dependency 'argon2', '~> 2.0'
21
+ gem.add_dependency 'devise', '~> 4.0'
22
+ gem.add_dependency 'argon2', '~> 2.1'
23
23
 
24
24
 
25
25
  gem.post_install_message = "Version 2 of devise-argon2 introduces breaking changes, please see README.md for details."
@@ -53,26 +53,49 @@ module Devise
53
53
  attributes = { encrypted_password: password_digest(password) }
54
54
  attributes[:password_salt] = nil if migrate_hash_from_devise_argon2_v1?
55
55
 
56
- self.assign_attributes(attributes)
57
- self.save if self.persisted?
56
+ if self.persisted?
57
+ update_without_callbacks(attributes)
58
+ else
59
+ self.assign_attributes(attributes)
60
+ end
61
+ end
62
+
63
+ def update_without_callbacks(attributes)
64
+ if defined?(Mongoid) && Mongoid.models.include?(self.class)
65
+ self.set(attributes)
66
+ else
67
+ self.update_columns(attributes)
68
+ end
58
69
  end
59
70
 
60
71
  def outdated_work_factors?
72
+ hash_format = ::Argon2::HashFormat.new(encrypted_password)
73
+ current_work_factors = {
74
+ t_cost: hash_format.t_cost,
75
+ m_cost: hash_format.m_cost,
76
+ p_cost: hash_format.p_cost
77
+ }
78
+ current_work_factors != configured_work_factors
79
+ end
80
+
81
+ def configured_work_factors
61
82
  # Since version 2.3.0 the argon2 gem exposes the default work factors via constants, see
62
83
  # https://github.com/technion/ruby-argon2/commit/d62ecf8b4ec6b8c1651fade5a5ebdc856e8aef42
63
- default_t_cost = defined?(::Argon2::Password::DEFAULT_T_COST) ? ::Argon2::Password::DEFAULT_T_COST : 2
64
- default_m_cost = defined?(::Argon2::Password::DEFAULT_M_COST) ? ::Argon2::Password::DEFAULT_M_COST : 16
65
- default_p_cost = defined?(::Argon2::Password::DEFAULT_P_COST) ? ::Argon2::Password::DEFAULT_P_COST : 1
84
+ work_factors = {
85
+ t_cost: defined?(::Argon2::Password::DEFAULT_T_COST) ? ::Argon2::Password::DEFAULT_T_COST : 2,
86
+ m_cost: defined?(::Argon2::Password::DEFAULT_M_COST) ? ::Argon2::Password::DEFAULT_M_COST : 16,
87
+ p_cost: defined?(::Argon2::Password::DEFAULT_P_COST) ? ::Argon2::Password::DEFAULT_P_COST : 1
88
+ }.merge(self.class.argon2_options.slice(:t_cost, :m_cost, :p_cost))
66
89
 
67
- current_t_cost = self.class.argon2_options[:t_cost] || default_t_cost
68
- current_m_cost = self.class.argon2_options[:m_cost] || default_m_cost
69
- current_p_cost = self.class.argon2_options[:p_cost] || default_p_cost
70
-
71
- hash_format = ::Argon2::HashFormat.new(encrypted_password)
90
+ # Since version 2.3.0 the argon2 gem supports defining work factors with named profiles, see
91
+ # https://github.com/technion/ruby-argon2/commit/6312a8fb3a6c6c5e771a736572e63d47485e8613
92
+ if self.class.argon2_options[:profile] && defined?(::Argon2::Profiles)
93
+ work_factors.merge!(::Argon2::Profiles[self.class.argon2_options[:profile]])
94
+ end
95
+
96
+ work_factors[:m_cost] = (1 << work_factors[:m_cost])
72
97
 
73
- hash_format.t_cost != current_t_cost ||
74
- hash_format.m_cost != (1 << current_m_cost) ||
75
- hash_format.p_cost != current_p_cost
98
+ work_factors
76
99
  end
77
100
 
78
101
  def migrate_hash_from_devise_argon2_v1?
@@ -1,5 +1,5 @@
1
1
  module Devise
2
2
  module Argon2
3
- ARGON2_VERSION = '2.0.0'
3
+ ARGON2_VERSION = '2.0.2'
4
4
  end
5
5
  end
@@ -19,6 +19,7 @@ describe Devise::Models::Argon2 do
19
19
  p_cost: DEFAULT_P_COST
20
20
  }
21
21
  User.destroy_all
22
+ OldUser.destroy_all
22
23
  end
23
24
 
24
25
  def work_factors(hash)
@@ -127,6 +128,14 @@ describe Devise::Models::Argon2 do
127
128
  it 'does not update the hash if an invalid password is given' do
128
129
  expect{ user.valid_password?(INCORRECT_PASSWORD) }.not_to(change(user, :encrypted_password))
129
130
  end
131
+
132
+ it 'does not send password change notification emails on hash updates' do
133
+ user.email = 'test@example.com'
134
+ user.save!
135
+ Devise.send_password_change_notification = true
136
+ expect{ user.valid_password?(CORRECT_PASSWORD) }
137
+ .not_to(change { ActionMailer::Base.deliveries.count })
138
+ end
130
139
  end
131
140
 
132
141
  describe 'updating outdated work factors' do
@@ -174,6 +183,55 @@ describe Devise::Models::Argon2 do
174
183
  .to({ m_cost: 1 << 4, t_cost: 3, p_cost: 2 })
175
184
  )
176
185
  end
186
+
187
+ if Argon2::VERSION >= '2.3.0'
188
+ it 'updates work factors if they changed via profile option' do
189
+ # Build user with argon2 default work factors (which match the RFC_9106_LOW_MEMORY
190
+ # profile.)
191
+ Devise.argon2_options = {}
192
+ user
193
+
194
+ Devise.argon2_options = { profile: :pre_rfc_9106 }
195
+
196
+ expect{ user.valid_password?(CORRECT_PASSWORD) }.to(
197
+ change{ work_factors(user.encrypted_password) }
198
+ .to(
199
+ {
200
+ m_cost: 1 << Argon2::Profiles[:pre_rfc_9106][:m_cost],
201
+ t_cost: Argon2::Profiles[:pre_rfc_9106][:t_cost],
202
+ p_cost: Argon2::Profiles[:pre_rfc_9106][:p_cost]
203
+ }
204
+ )
205
+ )
206
+ end
207
+
208
+ it 'gives precendence to the profile option over explicit configuration of work factors' do
209
+ Devise.argon2_options = {
210
+ m_cost: Argon2::Profiles[:pre_rfc_9106][:m_cost] + 1,
211
+ t_cost: Argon2::Profiles[:pre_rfc_9106][:t_cost] + 1,
212
+ p_cost: Argon2::Profiles[:pre_rfc_9106][:p_cost] + 1
213
+ }
214
+ user # build user
215
+
216
+ Devise.argon2_options = {
217
+ profile: :pre_rfc_9106,
218
+ m_cost: Argon2::Profiles[:pre_rfc_9106][:m_cost] + 1,
219
+ t_cost: Argon2::Profiles[:pre_rfc_9106][:t_cost] + 1,
220
+ p_cost: Argon2::Profiles[:pre_rfc_9106][:p_cost] + 1
221
+ }
222
+
223
+ expect{ user.valid_password?(CORRECT_PASSWORD) }.to(
224
+ change{ work_factors(user.encrypted_password) }
225
+ .to(
226
+ {
227
+ m_cost: 1 << Argon2::Profiles[:pre_rfc_9106][:m_cost],
228
+ t_cost: Argon2::Profiles[:pre_rfc_9106][:t_cost],
229
+ p_cost: Argon2::Profiles[:pre_rfc_9106][:p_cost]
230
+ }
231
+ )
232
+ )
233
+ end
234
+ end
177
235
  end
178
236
 
179
237
  it 'ignores migrate_from_devise_argon2_v1 if password_salt is not present' do
@@ -20,5 +20,7 @@ module DummyRailsApp
20
20
  config.eager_load = false
21
21
  config.autoload_paths.reject!{ |p| p =~ /\/app\/(\w+)$/ && !%w(controllers helpers mailers views).include?($1) }
22
22
  config.autoload_paths += ["#{config.root}/app/#{ORM}"]
23
+ config.action_mailer.delivery_method = :test
24
+ config.action_mailer.default_options = { from: 'test@example.com' }
23
25
  end
24
26
  end
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ devise_for :old_users
3
+ end
metadata CHANGED
@@ -1,43 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise-argon2
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tamas Erdos
8
+ - Moritz Höppner
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2023-10-16 00:00:00.000000000 Z
12
+ date: 2024-09-30 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: devise
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - ">="
18
+ - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: 2.1.0
20
+ version: '4.0'
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - ">="
25
+ - - "~>"
25
26
  - !ruby/object:Gem::Version
26
- version: 2.1.0
27
+ version: '4.0'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: argon2
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
32
  - - "~>"
32
33
  - !ruby/object:Gem::Version
33
- version: '2.0'
34
+ version: '2.1'
34
35
  type: :runtime
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
39
  - - "~>"
39
40
  - !ruby/object:Gem::Version
40
- version: '2.0'
41
+ version: '2.1'
41
42
  description: Enables Devise to hash passwords with Argon2id
42
43
  email:
43
44
  - tamas at tamaserdos com
@@ -77,6 +78,7 @@ files:
77
78
  - spec/rails_app/config/environment.rb
78
79
  - spec/rails_app/config/initializers/devise.rb
79
80
  - spec/rails_app/config/mongoid.yml
81
+ - spec/rails_app/config/routes.rb
80
82
  - spec/rails_app/db/migrate/20230617201921_devise_create_users.rb
81
83
  - spec/rails_app/db/migrate/20231004084147_devise_create_old_users.rb
82
84
  - spec/rails_app/db/schema.rb
@@ -101,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
103
  - !ruby/object:Gem::Version
102
104
  version: '0'
103
105
  requirements: []
104
- rubygems_version: 3.3.3
106
+ rubygems_version: 3.4.22
105
107
  signing_key:
106
108
  specification_version: 4
107
109
  summary: Enables Devise to hash passwords with Argon2id
@@ -126,6 +128,7 @@ test_files:
126
128
  - spec/rails_app/config/environment.rb
127
129
  - spec/rails_app/config/initializers/devise.rb
128
130
  - spec/rails_app/config/mongoid.yml
131
+ - spec/rails_app/config/routes.rb
129
132
  - spec/rails_app/db/migrate/20230617201921_devise_create_users.rb
130
133
  - spec/rails_app/db/migrate/20231004084147_devise_create_old_users.rb
131
134
  - spec/rails_app/db/schema.rb