doorkeeper 5.1.0.rc1 → 5.1.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +11 -2
- data/Appraisals +29 -3
- data/Gemfile +13 -5
- data/NEWS.md +52 -15
- data/README.md +68 -487
- data/app/controllers/doorkeeper/token_info_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +1 -1
- data/doorkeeper.gemspec +3 -2
- data/gemfiles/rails_4_2.gemfile +8 -5
- data/gemfiles/rails_5_0.gemfile +9 -6
- data/gemfiles/rails_5_1.gemfile +9 -6
- data/gemfiles/rails_5_2.gemfile +9 -6
- data/gemfiles/rails_6_0.gemfile +16 -0
- data/gemfiles/rails_master.gemfile +8 -10
- data/lib/doorkeeper.rb +7 -1
- data/lib/doorkeeper/config.rb +110 -24
- data/lib/doorkeeper/models/access_grant_mixin.rb +15 -7
- data/lib/doorkeeper/models/access_token_mixin.rb +29 -16
- data/lib/doorkeeper/models/application_mixin.rb +18 -28
- data/lib/doorkeeper/models/concerns/expirable.rb +3 -2
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +4 -0
- data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +3 -1
- data/lib/doorkeeper/oauth/error_response.rb +5 -1
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +12 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +4 -0
- data/lib/doorkeeper/oauth/token_introspection.rb +72 -6
- data/lib/doorkeeper/orm/active_record/access_grant.rb +9 -8
- data/lib/doorkeeper/orm/active_record/application.rb +10 -6
- data/lib/doorkeeper/secret_storing/base.rb +63 -0
- data/lib/doorkeeper/secret_storing/bcrypt.rb +59 -0
- data/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +25 -0
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/generators/doorkeeper/templates/initializer.rb +62 -20
- data/spec/controllers/authorizations_controller_spec.rb +3 -3
- data/spec/controllers/token_info_controller_spec.rb +1 -1
- data/spec/controllers/tokens_controller_spec.rb +78 -30
- data/spec/dummy/config/application.rb +12 -1
- data/spec/lib/config_spec.rb +119 -35
- data/spec/lib/models/expirable_spec.rb +12 -0
- data/spec/lib/models/reusable_spec.rb +40 -0
- data/spec/lib/models/scopes_spec.rb +13 -1
- data/spec/lib/models/secret_storable_spec.rb +113 -0
- data/spec/lib/oauth/authorization_code_request_spec.rb +18 -1
- data/spec/lib/oauth/client_credentials/creator_spec.rb +51 -7
- data/spec/lib/oauth/error_response_spec.rb +7 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +11 -1
- data/spec/lib/oauth/token_request_spec.rb +16 -1
- data/spec/lib/secret_storing/base_spec.rb +60 -0
- data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
- data/spec/lib/secret_storing/plain_spec.rb +44 -0
- data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
- data/spec/models/doorkeeper/application_spec.rb +23 -4
- data/spec/requests/flows/authorization_code_spec.rb +3 -3
- data/spec/requests/flows/client_credentials_spec.rb +2 -2
- data/spec/requests/flows/implicit_grant_spec.rb +1 -1
- data/spec/requests/flows/password_spec.rb +3 -3
- data/spec/routing/custom_controller_routes_spec.rb +4 -0
- data/spec/support/shared/hashing_shared_context.rb +12 -5
- metadata +51 -21
- data/lib/doorkeeper/models/concerns/hashable.rb +0 -137
- data/spec/lib/models/hashable_spec.rb +0 -183
@@ -1,7 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
shared_context 'with token hashing enabled' do
|
4
|
-
let(:hashed_or_plain_token_func)
|
4
|
+
let(:hashed_or_plain_token_func) do
|
5
|
+
Doorkeeper::SecretStoring::Sha256Hash.method(:transform_secret)
|
6
|
+
end
|
7
|
+
|
5
8
|
before do
|
6
9
|
Doorkeeper.configure do
|
7
10
|
hash_token_secrets
|
@@ -10,17 +13,21 @@ shared_context 'with token hashing enabled' do
|
|
10
13
|
end
|
11
14
|
|
12
15
|
shared_context 'with token hashing and fallback lookup enabled' do
|
13
|
-
let(:hashed_or_plain_token_func)
|
16
|
+
let(:hashed_or_plain_token_func) do
|
17
|
+
Doorkeeper::SecretStoring::Sha256Hash.method(:transform_secret)
|
18
|
+
end
|
19
|
+
|
14
20
|
before do
|
15
21
|
Doorkeeper.configure do
|
16
|
-
hash_token_secrets
|
17
|
-
fallback_to_plain_secrets
|
22
|
+
hash_token_secrets fallback: :plain
|
18
23
|
end
|
19
24
|
end
|
20
25
|
end
|
21
26
|
|
22
27
|
shared_context 'with application hashing enabled' do
|
23
|
-
let(:hashed_or_plain_token_func)
|
28
|
+
let(:hashed_or_plain_token_func) do
|
29
|
+
Doorkeeper::SecretStoring::Sha256Hash.method(:transform_secret)
|
30
|
+
end
|
24
31
|
before do
|
25
32
|
Doorkeeper.configure do
|
26
33
|
hash_application_secrets
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doorkeeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.1.0.
|
4
|
+
version: 5.1.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felipe Elias Philipp
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2019-
|
14
|
+
date: 2019-03-22 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: railties
|
@@ -28,21 +28,21 @@ dependencies:
|
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '4.2'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
-
name:
|
31
|
+
name: appraisal
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
requirements:
|
34
|
-
- - "
|
34
|
+
- - ">="
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: '
|
36
|
+
version: '0'
|
37
37
|
type: :development
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
|
-
- - "
|
41
|
+
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
43
|
+
version: '0'
|
44
44
|
- !ruby/object:Gem::Dependency
|
45
|
-
name:
|
45
|
+
name: capybara
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
47
47
|
requirements:
|
48
48
|
- - ">="
|
@@ -56,33 +56,33 @@ dependencies:
|
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
version: '0'
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
|
-
name:
|
59
|
+
name: coveralls
|
60
60
|
requirement: !ruby/object:Gem::Requirement
|
61
61
|
requirements:
|
62
|
-
- - "
|
62
|
+
- - ">="
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: '
|
64
|
+
version: '0'
|
65
65
|
type: :development
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
68
68
|
requirements:
|
69
|
-
- - "
|
69
|
+
- - ">="
|
70
70
|
- !ruby/object:Gem::Version
|
71
|
-
version: '
|
71
|
+
version: '0'
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
|
-
name:
|
73
|
+
name: danger
|
74
74
|
requirement: !ruby/object:Gem::Requirement
|
75
75
|
requirements:
|
76
|
-
- - "
|
76
|
+
- - "~>"
|
77
77
|
- !ruby/object:Gem::Version
|
78
|
-
version: '0'
|
78
|
+
version: '5.0'
|
79
79
|
type: :development
|
80
80
|
prerelease: false
|
81
81
|
version_requirements: !ruby/object:Gem::Requirement
|
82
82
|
requirements:
|
83
|
-
- - "
|
83
|
+
- - "~>"
|
84
84
|
- !ruby/object:Gem::Version
|
85
|
-
version: '0'
|
85
|
+
version: '5.0'
|
86
86
|
- !ruby/object:Gem::Dependency
|
87
87
|
name: database_cleaner
|
88
88
|
requirement: !ruby/object:Gem::Requirement
|
@@ -125,6 +125,20 @@ dependencies:
|
|
125
125
|
- - "~>"
|
126
126
|
- !ruby/object:Gem::Version
|
127
127
|
version: 0.9.3
|
128
|
+
- !ruby/object:Gem::Dependency
|
129
|
+
name: grape
|
130
|
+
requirement: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
type: :development
|
136
|
+
prerelease: false
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
128
142
|
- !ruby/object:Gem::Dependency
|
129
143
|
name: rake
|
130
144
|
requirement: !ruby/object:Gem::Requirement
|
@@ -212,6 +226,7 @@ files:
|
|
212
226
|
- gemfiles/rails_5_0.gemfile
|
213
227
|
- gemfiles/rails_5_1.gemfile
|
214
228
|
- gemfiles/rails_5_2.gemfile
|
229
|
+
- gemfiles/rails_6_0.gemfile
|
215
230
|
- gemfiles/rails_master.gemfile
|
216
231
|
- lib/doorkeeper.rb
|
217
232
|
- lib/doorkeeper/config.rb
|
@@ -225,11 +240,12 @@ files:
|
|
225
240
|
- lib/doorkeeper/models/application_mixin.rb
|
226
241
|
- lib/doorkeeper/models/concerns/accessible.rb
|
227
242
|
- lib/doorkeeper/models/concerns/expirable.rb
|
228
|
-
- lib/doorkeeper/models/concerns/hashable.rb
|
229
243
|
- lib/doorkeeper/models/concerns/orderable.rb
|
230
244
|
- lib/doorkeeper/models/concerns/ownership.rb
|
245
|
+
- lib/doorkeeper/models/concerns/reusable.rb
|
231
246
|
- lib/doorkeeper/models/concerns/revocable.rb
|
232
247
|
- lib/doorkeeper/models/concerns/scopes.rb
|
248
|
+
- lib/doorkeeper/models/concerns/secret_storable.rb
|
233
249
|
- lib/doorkeeper/oauth.rb
|
234
250
|
- lib/doorkeeper/oauth/authorization/code.rb
|
235
251
|
- lib/doorkeeper/oauth/authorization/context.rb
|
@@ -281,6 +297,10 @@ files:
|
|
281
297
|
- lib/doorkeeper/request/refresh_token.rb
|
282
298
|
- lib/doorkeeper/request/strategy.rb
|
283
299
|
- lib/doorkeeper/request/token.rb
|
300
|
+
- lib/doorkeeper/secret_storing/base.rb
|
301
|
+
- lib/doorkeeper/secret_storing/bcrypt.rb
|
302
|
+
- lib/doorkeeper/secret_storing/plain.rb
|
303
|
+
- lib/doorkeeper/secret_storing/sha256_hash.rb
|
284
304
|
- lib/doorkeeper/server.rb
|
285
305
|
- lib/doorkeeper/stale_records_cleaner.rb
|
286
306
|
- lib/doorkeeper/validations.rb
|
@@ -360,9 +380,10 @@ files:
|
|
360
380
|
- spec/lib/config_spec.rb
|
361
381
|
- spec/lib/doorkeeper_spec.rb
|
362
382
|
- spec/lib/models/expirable_spec.rb
|
363
|
-
- spec/lib/models/
|
383
|
+
- spec/lib/models/reusable_spec.rb
|
364
384
|
- spec/lib/models/revocable_spec.rb
|
365
385
|
- spec/lib/models/scopes_spec.rb
|
386
|
+
- spec/lib/models/secret_storable_spec.rb
|
366
387
|
- spec/lib/oauth/authorization/uri_builder_spec.rb
|
367
388
|
- spec/lib/oauth/authorization_code_request_spec.rb
|
368
389
|
- spec/lib/oauth/base_request_spec.rb
|
@@ -391,6 +412,10 @@ files:
|
|
391
412
|
- spec/lib/oauth/token_response_spec.rb
|
392
413
|
- spec/lib/oauth/token_spec.rb
|
393
414
|
- spec/lib/request/strategy_spec.rb
|
415
|
+
- spec/lib/secret_storing/base_spec.rb
|
416
|
+
- spec/lib/secret_storing/bcrypt_spec.rb
|
417
|
+
- spec/lib/secret_storing/plain_spec.rb
|
418
|
+
- spec/lib/secret_storing/sha256_hash_spec.rb
|
394
419
|
- spec/lib/server_spec.rb
|
395
420
|
- spec/lib/stale_records_cleaner_spec.rb
|
396
421
|
- spec/models/doorkeeper/access_grant_spec.rb
|
@@ -518,9 +543,10 @@ test_files:
|
|
518
543
|
- spec/lib/config_spec.rb
|
519
544
|
- spec/lib/doorkeeper_spec.rb
|
520
545
|
- spec/lib/models/expirable_spec.rb
|
521
|
-
- spec/lib/models/
|
546
|
+
- spec/lib/models/reusable_spec.rb
|
522
547
|
- spec/lib/models/revocable_spec.rb
|
523
548
|
- spec/lib/models/scopes_spec.rb
|
549
|
+
- spec/lib/models/secret_storable_spec.rb
|
524
550
|
- spec/lib/oauth/authorization/uri_builder_spec.rb
|
525
551
|
- spec/lib/oauth/authorization_code_request_spec.rb
|
526
552
|
- spec/lib/oauth/base_request_spec.rb
|
@@ -549,6 +575,10 @@ test_files:
|
|
549
575
|
- spec/lib/oauth/token_response_spec.rb
|
550
576
|
- spec/lib/oauth/token_spec.rb
|
551
577
|
- spec/lib/request/strategy_spec.rb
|
578
|
+
- spec/lib/secret_storing/base_spec.rb
|
579
|
+
- spec/lib/secret_storing/bcrypt_spec.rb
|
580
|
+
- spec/lib/secret_storing/plain_spec.rb
|
581
|
+
- spec/lib/secret_storing/sha256_hash_spec.rb
|
552
582
|
- spec/lib/server_spec.rb
|
553
583
|
- spec/lib/stale_records_cleaner_spec.rb
|
554
584
|
- spec/models/doorkeeper/access_grant_spec.rb
|
@@ -1,137 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Doorkeeper
|
4
|
-
module Models
|
5
|
-
##
|
6
|
-
# Hashable finder to provide lookups for input plaintext values which are
|
7
|
-
# mapped to their hashes before lookup.
|
8
|
-
module Hashable
|
9
|
-
extend ActiveSupport::Concern
|
10
|
-
|
11
|
-
delegate :perform_secret_hashing?,
|
12
|
-
:hashed_or_plain_token,
|
13
|
-
to: :class
|
14
|
-
|
15
|
-
# :nodoc
|
16
|
-
module ClassMethods
|
17
|
-
# Allow to override the hashing method by the including module
|
18
|
-
attr_accessor :secret_hash_function, :secret_comparer
|
19
|
-
|
20
|
-
# Compare the given plaintext with the secret
|
21
|
-
#
|
22
|
-
# @param input [String]
|
23
|
-
# The plain input to compare.
|
24
|
-
#
|
25
|
-
# @param secret [String]
|
26
|
-
# The secret value to compare with.
|
27
|
-
#
|
28
|
-
# @return [Boolean]
|
29
|
-
# If hashing is enabled: Whether the secret equals hashed input
|
30
|
-
# If hashing is disabled: Whether input matches secret
|
31
|
-
#
|
32
|
-
def secret_matches?(input, secret)
|
33
|
-
unless perform_secret_hashing?
|
34
|
-
return ActiveSupport::SecurityUtils.secure_compare input, secret
|
35
|
-
end
|
36
|
-
|
37
|
-
(secret_comparer || method(:default_comparer))
|
38
|
-
.call(input, secret)
|
39
|
-
end
|
40
|
-
|
41
|
-
# Returns an instance of the Doorkeeper::AccessToken with
|
42
|
-
# specific token value.
|
43
|
-
#
|
44
|
-
# @param attr [Symbol]
|
45
|
-
# The token attribute we're looking with.
|
46
|
-
#
|
47
|
-
# @param token [#to_s]
|
48
|
-
# token value (any object that responds to `#to_s`)
|
49
|
-
#
|
50
|
-
# @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
|
51
|
-
# if there is no record with such token
|
52
|
-
#
|
53
|
-
def find_by_plaintext_token(attr, token)
|
54
|
-
token = token.to_s
|
55
|
-
|
56
|
-
find_by(attr => hashed_or_plain_token(token)) ||
|
57
|
-
find_by_fallback_token(attr, token)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Allow looking up previously plain tokens as a fallback
|
61
|
-
# IFF respective options are enabled
|
62
|
-
#
|
63
|
-
# @param attr [Symbol]
|
64
|
-
# The token attribute we're looking with.
|
65
|
-
#
|
66
|
-
# @param token [#to_s]
|
67
|
-
# token value (any object that responds to `#to_s`)
|
68
|
-
#
|
69
|
-
# @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
|
70
|
-
# if there is no record with such token
|
71
|
-
#
|
72
|
-
def find_by_fallback_token(attr, token)
|
73
|
-
return nil unless perform_secret_hashing?
|
74
|
-
return nil unless Doorkeeper.configuration.fallback_to_plain_secrets?
|
75
|
-
|
76
|
-
find_by(attr => token).tap do |fallback|
|
77
|
-
upgrade_fallback_value fallback, attr
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Hash the given input token
|
82
|
-
#
|
83
|
-
# @param plain_token [String]
|
84
|
-
# The plain text token to hash.
|
85
|
-
#
|
86
|
-
# @return [String]
|
87
|
-
# IFF secret hashing enabled, the hashed token,
|
88
|
-
# otherwise returns the plain token.
|
89
|
-
def hashed_or_plain_token(plain_token)
|
90
|
-
if perform_secret_hashing?
|
91
|
-
(secret_hash_function || method(:default_hash_function))
|
92
|
-
.call plain_token
|
93
|
-
else
|
94
|
-
plain_token
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Allow implementations in ORMs to replace a plain
|
99
|
-
# value falling back to to avoid it remaining as plain text.
|
100
|
-
#
|
101
|
-
# @param instance
|
102
|
-
# An instance of this model with a plain value token.
|
103
|
-
#
|
104
|
-
# @param attr
|
105
|
-
# The token attribute to upgrade
|
106
|
-
#
|
107
|
-
def upgrade_fallback_value(instance, attr)
|
108
|
-
plain_token = instance.public_send attr
|
109
|
-
instance.update_column(attr, hashed_or_plain_token(plain_token))
|
110
|
-
end
|
111
|
-
|
112
|
-
# Including classes can override this function to
|
113
|
-
# disable or enable secret hashing dynamically
|
114
|
-
def perform_secret_hashing?
|
115
|
-
true
|
116
|
-
end
|
117
|
-
|
118
|
-
# Return a default hashing function to be used when including
|
119
|
-
# module or user does not specify what to use
|
120
|
-
# @param plain_token [String]
|
121
|
-
# The plain text token to hash.
|
122
|
-
#
|
123
|
-
# @return [String] Hashed plain text token
|
124
|
-
#
|
125
|
-
def default_hash_function(plain_token)
|
126
|
-
::Digest::SHA256.hexdigest plain_token
|
127
|
-
end
|
128
|
-
|
129
|
-
# Return a default comparer for the given hash function
|
130
|
-
def default_comparer(plain, secret)
|
131
|
-
hashed = hashed_or_plain_token(plain)
|
132
|
-
ActiveSupport::SecurityUtils.secure_compare hashed, secret
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
@@ -1,183 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe 'Hashable' do
|
6
|
-
let(:clazz) do
|
7
|
-
Class.new do
|
8
|
-
include Doorkeeper::Models::Hashable
|
9
|
-
|
10
|
-
def self.find_by(*)
|
11
|
-
raise 'stub this'
|
12
|
-
end
|
13
|
-
|
14
|
-
def update_column(*)
|
15
|
-
raise 'stub this'
|
16
|
-
end
|
17
|
-
|
18
|
-
def token
|
19
|
-
raise 'stub this'
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe :hashed_or_plain_token do
|
25
|
-
let(:enabled_hashing?) { false }
|
26
|
-
subject { clazz.send(:hashed_or_plain_token, 'input') }
|
27
|
-
|
28
|
-
before do
|
29
|
-
allow(clazz).to receive(:perform_secret_hashing?)
|
30
|
-
.and_return enabled_hashing?
|
31
|
-
end
|
32
|
-
|
33
|
-
context 'when no hash function set' do
|
34
|
-
it 'returns the plain input' do
|
35
|
-
expect(subject).to eq 'input'
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'when hashing enabled' do
|
39
|
-
let(:enabled_hashing?) { true }
|
40
|
-
|
41
|
-
it 'uses the default function' do
|
42
|
-
expect(clazz)
|
43
|
-
.to receive(:default_hash_function)
|
44
|
-
.with('input')
|
45
|
-
.and_call_original
|
46
|
-
|
47
|
-
expect(subject).not_to eq 'input'
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'when hash_function defined' do
|
53
|
-
let(:hash_function) { ->(input) { input + '-hashed' } }
|
54
|
-
|
55
|
-
before do
|
56
|
-
clazz.secret_hash_function = hash_function
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'returns the plain input' do
|
60
|
-
expect(clazz).not_to receive(:default_hash_function)
|
61
|
-
expect(subject).to eq 'input'
|
62
|
-
end
|
63
|
-
|
64
|
-
context 'when hashing enabled' do
|
65
|
-
let(:enabled_hashing?) { true }
|
66
|
-
|
67
|
-
it 'uses that function' do
|
68
|
-
expect(hash_function)
|
69
|
-
.to receive(:call)
|
70
|
-
.with('input')
|
71
|
-
.and_call_original
|
72
|
-
|
73
|
-
expect(subject).to eq 'input-hashed'
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe :secret_matches? do
|
80
|
-
context 'when comparer undefined' do
|
81
|
-
it 'uses a default compare' do
|
82
|
-
expect(clazz).to receive(:default_comparer).with('a', 'a').and_return true
|
83
|
-
expect(clazz.secret_matches?('a', 'a')).to be_truthy
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
context 'when comparer defined' do
|
88
|
-
let(:comparer) do
|
89
|
-
->(*) { false }
|
90
|
-
end
|
91
|
-
|
92
|
-
before do
|
93
|
-
clazz.secret_comparer = comparer
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'uses that comparer' do
|
97
|
-
expect(comparer).to receive(:call).with('a', 'a').and_call_original
|
98
|
-
expect(clazz.secret_matches?('a', 'a')).to be_falsey
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
describe :find_by_fallback_token do
|
104
|
-
let(:old_token) { instance_double(clazz, token: 'input') }
|
105
|
-
subject { clazz.send(:find_by_fallback_token, :token, 'input') }
|
106
|
-
|
107
|
-
it 'does not call find_by when not configured' do
|
108
|
-
expect(clazz).not_to receive(:find_by)
|
109
|
-
expect(subject).to eq(nil)
|
110
|
-
end
|
111
|
-
|
112
|
-
context 'when fallback configured' do
|
113
|
-
include_context 'with token hashing and fallback lookup enabled'
|
114
|
-
let(:hashed_token) { hashed_or_plain_token_func.call('input') }
|
115
|
-
|
116
|
-
it 'upgrades the plain token if no hashed exists' do
|
117
|
-
expect(clazz).to receive(:find_by).with(token: 'input').and_return(old_token)
|
118
|
-
expect(old_token).to receive(:update_column).with(:token, hashed_token)
|
119
|
-
|
120
|
-
expect(subject).to eq(old_token)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
describe :find_by_plaintext_token do
|
126
|
-
let(:plain_token) { 'asdf' }
|
127
|
-
let(:subject) { clazz.send(:find_by_plaintext_token, :token, plain_token) }
|
128
|
-
let(:hashing_enabled?) { false }
|
129
|
-
|
130
|
-
before do
|
131
|
-
allow(clazz).to receive(:perform_secret_hashing?).and_return(hashing_enabled?)
|
132
|
-
end
|
133
|
-
|
134
|
-
context 'when not configured' do
|
135
|
-
it 'always finds with the plain value even when nil' do
|
136
|
-
expect(clazz).to receive(:find_by).with(token: plain_token).once.and_return(nil)
|
137
|
-
expect(subject).to eq(nil)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
context 'when hashing configured' do
|
142
|
-
let(:hashing_enabled?) { true }
|
143
|
-
let(:hashed_token) { clazz.send(:default_hash_function, plain_token) }
|
144
|
-
|
145
|
-
it 'calls find_by only on the hashed value if it returns' do
|
146
|
-
expect(clazz).not_to receive(:find_by).with(token: plain_token)
|
147
|
-
expect(clazz).to receive(:find_by).with(token: hashed_token).and_return(:result)
|
148
|
-
|
149
|
-
expect(subject).to eq(:result)
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'does not fall back to plain token' do
|
153
|
-
expect(clazz).not_to receive(:find_by).with(token: plain_token)
|
154
|
-
expect(clazz).to receive(:find_by).with(token: hashed_token).and_return(nil)
|
155
|
-
|
156
|
-
expect(subject).to eq(nil)
|
157
|
-
end
|
158
|
-
|
159
|
-
context 'when fallback configured' do
|
160
|
-
let(:old_token) { instance_double(clazz, token: plain_token) }
|
161
|
-
let(:hashed_token) { hashed_or_plain_token_func.call(plain_token) }
|
162
|
-
|
163
|
-
include_context 'with token hashing and fallback lookup enabled'
|
164
|
-
|
165
|
-
it 'does not fallback if found by hashed token' do
|
166
|
-
expect(clazz).to receive(:find_by).with(token: hashed_token).and_return old_token
|
167
|
-
expect(clazz).not_to receive(:find_by).with(token: plain_token)
|
168
|
-
expect(clazz).not_to receive(:upgrade_fallback_value)
|
169
|
-
|
170
|
-
expect(subject).to eq(old_token)
|
171
|
-
end
|
172
|
-
|
173
|
-
it 'also searches for the plain token if no hashed exists' do
|
174
|
-
expect(clazz).to receive(:find_by).with(token: hashed_token).and_return nil
|
175
|
-
expect(clazz).to receive(:find_by).with(token: plain_token).and_return(old_token)
|
176
|
-
expect(old_token).to receive(:update_column).with(:token, hashed_token)
|
177
|
-
|
178
|
-
expect(subject).to eq(old_token)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|