clearance 2.1.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of clearance might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.erb-lint.yml +5 -0
- data/.github/workflows/tests.yml +52 -0
- data/Appraisals +14 -19
- data/Gemfile +11 -7
- data/Gemfile.lock +140 -85
- data/NEWS.md +62 -0
- data/README.md +23 -12
- data/RELEASING.md +25 -0
- data/Rakefile +6 -1
- data/app/controllers/clearance/passwords_controller.rb +2 -3
- data/app/views/clearance_mailer/change_password.html.erb +2 -2
- data/app/views/clearance_mailer/change_password.text.erb +2 -2
- data/app/views/passwords/edit.html.erb +1 -1
- data/clearance.gemspec +1 -0
- data/gemfiles/rails_5.0.gemfile +10 -9
- data/gemfiles/rails_5.1.gemfile +11 -10
- data/gemfiles/rails_5.2.gemfile +11 -10
- data/gemfiles/rails_6.0.gemfile +11 -10
- data/gemfiles/rails_6.1.gemfile +21 -0
- data/lib/clearance/back_door.rb +2 -1
- data/lib/clearance/configuration.rb +19 -0
- data/lib/clearance/password_strategies.rb +2 -5
- data/lib/clearance/password_strategies/argon2.rb +23 -0
- data/lib/clearance/rack_session.rb +1 -1
- data/lib/clearance/session.rb +24 -12
- data/lib/clearance/user.rb +11 -2
- data/lib/clearance/version.rb +1 -1
- data/lib/generators/clearance/install/install_generator.rb +4 -1
- data/spec/clearance/back_door_spec.rb +20 -4
- data/spec/clearance/rack_session_spec.rb +1 -2
- data/spec/clearance/session_spec.rb +116 -43
- data/spec/configuration_spec.rb +28 -0
- data/spec/generators/clearance/install/install_generator_spec.rb +8 -2
- data/spec/mailers/clearance_mailer_spec.rb +33 -0
- data/spec/models/user_spec.rb +29 -0
- data/spec/password_strategies/argon2_spec.rb +79 -0
- data/spec/support/clearance.rb +11 -0
- data/spec/support/request_with_remember_token.rb +8 -6
- metadata +29 -4
- data/.travis.yml +0 -27
@@ -55,4 +55,37 @@ describe ClearanceMailer do
|
|
55
55
|
text: I18n.t("clearance_mailer.change_password.link_text")
|
56
56
|
)
|
57
57
|
end
|
58
|
+
|
59
|
+
context "when using a custom model" do
|
60
|
+
it "contains a link for a custom model" do
|
61
|
+
define_people_routes
|
62
|
+
Person = Class.new(User)
|
63
|
+
person = Person.new(email: "person@example.com", password: "password")
|
64
|
+
|
65
|
+
person.forgot_password!
|
66
|
+
host = ActionMailer::Base.default_url_options[:host]
|
67
|
+
link = "http://#{host}/people/#{person.id}/password/edit" \
|
68
|
+
"?token=#{person.confirmation_token}"
|
69
|
+
|
70
|
+
email = ClearanceMailer.change_password(person)
|
71
|
+
|
72
|
+
expect(email.text_part.body).to include(link)
|
73
|
+
expect(email.html_part.body).to include(link)
|
74
|
+
|
75
|
+
Object.send(:remove_const, :Person)
|
76
|
+
Rails.application.reload_routes!
|
77
|
+
end
|
78
|
+
|
79
|
+
def define_people_routes
|
80
|
+
Rails.application.routes.draw do
|
81
|
+
resources :people, controller: "clearance/users", only: :create do
|
82
|
+
resource(
|
83
|
+
:password,
|
84
|
+
controller: "clearance/passwords",
|
85
|
+
only: %i[edit update],
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
58
91
|
end
|
data/spec/models/user_spec.rb
CHANGED
@@ -47,6 +47,35 @@ describe User do
|
|
47
47
|
expect(User.authenticate(user.email, "bad_password")).to be_nil
|
48
48
|
end
|
49
49
|
|
50
|
+
it "takes the same amount of time to authenticate regardless of whether user exists" do
|
51
|
+
user = create(:user)
|
52
|
+
password = user.password
|
53
|
+
|
54
|
+
user_exists_time = Benchmark.realtime do
|
55
|
+
User.authenticate(user.email, password)
|
56
|
+
end
|
57
|
+
|
58
|
+
user_does_not_exist_time = Benchmark.realtime do
|
59
|
+
User.authenticate("bad_email@example.com", password)
|
60
|
+
end
|
61
|
+
|
62
|
+
expect(user_does_not_exist_time). to be_within(0.01).of(user_exists_time)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "takes the same amount of time to fail authentication regardless of whether user exists" do
|
66
|
+
user = create(:user)
|
67
|
+
|
68
|
+
user_exists_time = Benchmark.realtime do
|
69
|
+
User.authenticate(user.email, "bad_password")
|
70
|
+
end
|
71
|
+
|
72
|
+
user_does_not_exist_time = Benchmark.realtime do
|
73
|
+
User.authenticate("bad_email@example.com", "bad_password")
|
74
|
+
end
|
75
|
+
|
76
|
+
expect(user_does_not_exist_time). to be_within(0.01).of(user_exists_time)
|
77
|
+
end
|
78
|
+
|
50
79
|
it "is retrieved via a case-insensitive search" do
|
51
80
|
user = create(:user)
|
52
81
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Clearance::PasswordStrategies::Argon2 do
|
4
|
+
include FakeModelWithPasswordStrategy
|
5
|
+
|
6
|
+
describe "#password=" do
|
7
|
+
it "encrypts the password into encrypted_password" do
|
8
|
+
stub_argon2_password
|
9
|
+
model_instance = fake_model_with_argon2_strategy
|
10
|
+
|
11
|
+
model_instance.password = password
|
12
|
+
|
13
|
+
expect(model_instance.encrypted_password).to eq encrypted_password
|
14
|
+
end
|
15
|
+
|
16
|
+
it "encrypts with Argon2 using default cost in non test environments" do
|
17
|
+
hasher = stub_argon2_password
|
18
|
+
model_instance = fake_model_with_argon2_strategy
|
19
|
+
allow(Rails).to receive(:env).
|
20
|
+
and_return(ActiveSupport::StringInquirer.new("production"))
|
21
|
+
|
22
|
+
model_instance.password = password
|
23
|
+
|
24
|
+
expect(hasher).to have_received(:create).with(password)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "encrypts with Argon2 using minimum cost in test environment" do
|
28
|
+
hasher = stub_argon2_password
|
29
|
+
model_instance = fake_model_with_argon2_strategy
|
30
|
+
|
31
|
+
model_instance.password = password
|
32
|
+
|
33
|
+
expect(hasher).to have_received(:create).with(password)
|
34
|
+
end
|
35
|
+
|
36
|
+
def stub_argon2_password
|
37
|
+
hasher = double(Argon2::Password)
|
38
|
+
allow(hasher).to receive(:create).and_return(encrypted_password)
|
39
|
+
allow(Argon2::Password).to receive(:new).and_return(hasher)
|
40
|
+
hasher
|
41
|
+
end
|
42
|
+
|
43
|
+
def encrypted_password
|
44
|
+
@encrypted_password ||= double("encrypted password")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#authenticated?" do
|
49
|
+
context "given a password" do
|
50
|
+
it "is authenticated with Argon2" do
|
51
|
+
model_instance = fake_model_with_argon2_strategy
|
52
|
+
|
53
|
+
model_instance.password = password
|
54
|
+
|
55
|
+
expect(model_instance).to be_authenticated(password)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "given no password" do
|
60
|
+
it "is not authenticated" do
|
61
|
+
model_instance = fake_model_with_argon2_strategy
|
62
|
+
|
63
|
+
password = nil
|
64
|
+
|
65
|
+
expect(model_instance).not_to be_authenticated(password)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def fake_model_with_argon2_strategy
|
71
|
+
@fake_model_with_argon2_strategy ||= fake_model_with_password_strategy(
|
72
|
+
Clearance::PasswordStrategies::Argon2,
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
def password
|
77
|
+
"password"
|
78
|
+
end
|
79
|
+
end
|
data/spec/support/clearance.rb
CHANGED
@@ -4,6 +4,17 @@ Clearance.configure do |config|
|
|
4
4
|
# need an empty block to initialize the configuration object
|
5
5
|
end
|
6
6
|
|
7
|
+
# NOTE: to run the entire suite with signed cookies
|
8
|
+
# you can set the signed_cookie default to true
|
9
|
+
# and run all specs.
|
10
|
+
# However, to fake the actual signing process you
|
11
|
+
# can monkey-patch ActionDispatch so signed cookies
|
12
|
+
# behave like normal ones
|
13
|
+
#
|
14
|
+
# class ActionDispatch::Cookies::CookieJar
|
15
|
+
# def signed; self; end
|
16
|
+
# end
|
17
|
+
|
7
18
|
module Clearance
|
8
19
|
module Test
|
9
20
|
module Redirects
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module RememberTokenHelpers
|
2
2
|
def request_with_remember_token(remember_token)
|
3
|
-
cookies = {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
cookies = ActionDispatch::Request.new({}).cookie_jar
|
4
|
+
if Clearance.configuration.signed_cookie
|
5
|
+
cookies.signed[Clearance.configuration.cookie_name] = remember_token
|
6
|
+
else
|
7
|
+
cookies[Clearance.configuration.cookie_name] = remember_token
|
8
|
+
end
|
9
|
+
|
10
|
+
env = { clearance: Clearance::Session.new(cookies.request.env) }
|
9
11
|
Rack::Request.new env
|
10
12
|
end
|
11
13
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clearance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Croak
|
@@ -25,7 +25,7 @@ authors:
|
|
25
25
|
autorequire:
|
26
26
|
bindir: bin
|
27
27
|
cert_chain: []
|
28
|
-
date:
|
28
|
+
date: 2021-04-09 00:00:00.000000000 Z
|
29
29
|
dependencies:
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: bcrypt
|
@@ -41,6 +41,26 @@ dependencies:
|
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: 3.1.1
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: argon2
|
46
|
+
requirement: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - "~>"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '2.0'
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.0.2
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2.0'
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 2.0.2
|
44
64
|
- !ruby/object:Gem::Dependency
|
45
65
|
name: email_validator
|
46
66
|
requirement: !ruby/object:Gem::Requirement
|
@@ -124,8 +144,9 @@ extra_rdoc_files:
|
|
124
144
|
- LICENSE
|
125
145
|
- README.md
|
126
146
|
files:
|
147
|
+
- ".erb-lint.yml"
|
148
|
+
- ".github/workflows/tests.yml"
|
127
149
|
- ".gitignore"
|
128
|
-
- ".travis.yml"
|
129
150
|
- ".yardopts"
|
130
151
|
- Appraisals
|
131
152
|
- CONTRIBUTING.md
|
@@ -134,6 +155,7 @@ files:
|
|
134
155
|
- LICENSE
|
135
156
|
- NEWS.md
|
136
157
|
- README.md
|
158
|
+
- RELEASING.md
|
137
159
|
- Rakefile
|
138
160
|
- app/controllers/clearance/base_controller.rb
|
139
161
|
- app/controllers/clearance/passwords_controller.rb
|
@@ -162,6 +184,7 @@ files:
|
|
162
184
|
- gemfiles/rails_5.1.gemfile
|
163
185
|
- gemfiles/rails_5.2.gemfile
|
164
186
|
- gemfiles/rails_6.0.gemfile
|
187
|
+
- gemfiles/rails_6.1.gemfile
|
165
188
|
- lib/clearance.rb
|
166
189
|
- lib/clearance/authentication.rb
|
167
190
|
- lib/clearance/authorization.rb
|
@@ -174,6 +197,7 @@ files:
|
|
174
197
|
- lib/clearance/default_sign_in_guard.rb
|
175
198
|
- lib/clearance/engine.rb
|
176
199
|
- lib/clearance/password_strategies.rb
|
200
|
+
- lib/clearance/password_strategies/argon2.rb
|
177
201
|
- lib/clearance/password_strategies/bcrypt.rb
|
178
202
|
- lib/clearance/rack_session.rb
|
179
203
|
- lib/clearance/rspec.rb
|
@@ -250,6 +274,7 @@ files:
|
|
250
274
|
- spec/helpers/helper_helpers_spec.rb
|
251
275
|
- spec/mailers/clearance_mailer_spec.rb
|
252
276
|
- spec/models/user_spec.rb
|
277
|
+
- spec/password_strategies/argon2_spec.rb
|
253
278
|
- spec/password_strategies/bcrypt_spec.rb
|
254
279
|
- spec/password_strategies/password_strategies_spec.rb
|
255
280
|
- spec/requests/authentication_cookie_spec.rb
|
@@ -286,7 +311,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
286
311
|
- !ruby/object:Gem::Version
|
287
312
|
version: '0'
|
288
313
|
requirements: []
|
289
|
-
rubygems_version: 3.
|
314
|
+
rubygems_version: 3.1.2
|
290
315
|
signing_key:
|
291
316
|
specification_version: 4
|
292
317
|
summary: Rails authentication & authorization with email & password.
|
data/.travis.yml
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
cache: bundler
|
2
|
-
|
3
|
-
language:
|
4
|
-
- ruby
|
5
|
-
|
6
|
-
rvm:
|
7
|
-
- 2.4.9
|
8
|
-
- 2.5.7
|
9
|
-
- 2.6.5
|
10
|
-
|
11
|
-
gemfile:
|
12
|
-
- gemfiles/rails_5.0.gemfile
|
13
|
-
- gemfiles/rails_5.1.gemfile
|
14
|
-
- gemfiles/rails_5.2.gemfile
|
15
|
-
- gemfiles/rails_6.0.gemfile
|
16
|
-
|
17
|
-
install:
|
18
|
-
- "bin/setup"
|
19
|
-
|
20
|
-
branches:
|
21
|
-
only:
|
22
|
-
- master
|
23
|
-
|
24
|
-
matrix:
|
25
|
-
exclude:
|
26
|
-
- rvm: 2.4.9
|
27
|
-
gemfile: gemfiles/rails_6.0.gemfile
|