doorkeeper 5.2.2 → 5.3.0
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 +4 -4
- data/Appraisals +2 -2
- data/CHANGELOG.md +29 -2
- data/Gemfile +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +2 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -2
- data/app/controllers/doorkeeper/applications_controller.rb +0 -1
- data/app/controllers/doorkeeper/authorizations_controller.rb +2 -2
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
- data/gemfiles/rails_5_0.gemfile +2 -2
- data/gemfiles/rails_5_1.gemfile +2 -2
- data/gemfiles/rails_5_2.gemfile +2 -2
- data/gemfiles/rails_6_0.gemfile +2 -2
- data/gemfiles/rails_master.gemfile +2 -2
- data/lib/doorkeeper/config.rb +71 -38
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/helpers/controller.rb +10 -8
- data/lib/doorkeeper/models/access_grant_mixin.rb +7 -6
- data/lib/doorkeeper/models/access_token_mixin.rb +56 -18
- data/lib/doorkeeper/models/application_mixin.rb +3 -3
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
- data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +0 -27
- data/lib/doorkeeper/oauth/authorization/code.rb +4 -4
- data/lib/doorkeeper/oauth/authorization/token.rb +9 -6
- data/lib/doorkeeper/oauth/authorization_code_request.rb +13 -6
- data/lib/doorkeeper/oauth/base_request.rb +8 -4
- data/lib/doorkeeper/oauth/client.rb +7 -8
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +16 -9
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -7
- data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +4 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +5 -5
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +7 -5
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -1
- data/lib/doorkeeper/oauth/invalid_request_response.rb +3 -3
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -3
- data/lib/doorkeeper/oauth/pre_authorization.rb +12 -7
- data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -5
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +6 -6
- data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
- data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
- data/lib/doorkeeper/orm/active_record/application.rb +5 -95
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +53 -0
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +47 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +128 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +3 -3
- data/lib/doorkeeper/orm/active_record.rb +3 -4
- data/lib/doorkeeper/rails/helpers.rb +4 -4
- data/lib/doorkeeper/rails/routes.rb +5 -7
- data/lib/doorkeeper/rake/db.rake +3 -3
- data/lib/doorkeeper/request/authorization_code.rb +3 -3
- data/lib/doorkeeper/request/client_credentials.rb +2 -2
- data/lib/doorkeeper/request/password.rb +2 -2
- data/lib/doorkeeper/request/refresh_token.rb +3 -3
- data/lib/doorkeeper/request.rb +1 -1
- data/lib/doorkeeper/server.rb +1 -1
- data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
- data/lib/doorkeeper/version.rb +2 -2
- data/lib/doorkeeper.rb +2 -3
- data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
- data/lib/generators/doorkeeper/migration_generator.rb +1 -1
- data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +2 -2
- data/lib/generators/doorkeeper/templates/initializer.rb +39 -0
- data/spec/controllers/application_metal_controller_spec.rb +1 -1
- data/spec/controllers/applications_controller_spec.rb +3 -2
- data/spec/controllers/authorizations_controller_spec.rb +18 -18
- data/spec/controllers/protected_resources_controller_spec.rb +25 -17
- data/spec/controllers/token_info_controller_spec.rb +1 -1
- data/spec/controllers/tokens_controller_spec.rb +1 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -3
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +1 -1
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +1 -1
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/previous_refresh_token_generator_spec.rb +2 -2
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +62 -7
- data/spec/lib/doorkeeper_spec.rb +1 -1
- data/spec/lib/models/revocable_spec.rb +3 -3
- data/spec/lib/oauth/authorization_code_request_spec.rb +127 -125
- data/spec/lib/oauth/base_request_spec.rb +160 -158
- data/spec/lib/oauth/base_response_spec.rb +27 -29
- data/spec/lib/oauth/client/credentials_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials/creator_spec.rb +42 -5
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +12 -12
- data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
- data/spec/lib/oauth/client_credentials_integration_spec.rb +16 -18
- data/spec/lib/oauth/client_credentials_request_spec.rb +78 -80
- data/spec/lib/oauth/client_spec.rb +26 -26
- data/spec/lib/oauth/code_request_spec.rb +34 -34
- data/spec/lib/oauth/code_response_spec.rb +21 -25
- data/spec/lib/oauth/error_response_spec.rb +42 -44
- data/spec/lib/oauth/error_spec.rb +12 -14
- data/spec/lib/oauth/forbidden_token_response_spec.rb +11 -13
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +30 -18
- data/spec/lib/oauth/invalid_request_response_spec.rb +48 -50
- data/spec/lib/oauth/invalid_token_response_spec.rb +32 -34
- data/spec/lib/oauth/password_access_token_request_spec.rb +145 -147
- data/spec/lib/oauth/pre_authorization_spec.rb +159 -161
- data/spec/lib/oauth/refresh_token_request_spec.rb +138 -139
- data/spec/lib/oauth/scopes_spec.rb +104 -106
- data/spec/lib/oauth/token_request_spec.rb +115 -111
- data/spec/lib/oauth/token_response_spec.rb +71 -73
- data/spec/lib/oauth/token_spec.rb +121 -123
- data/spec/models/doorkeeper/access_grant_spec.rb +3 -5
- data/spec/models/doorkeeper/access_token_spec.rb +7 -7
- data/spec/models/doorkeeper/application_spec.rb +104 -77
- data/spec/requests/applications/applications_request_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +5 -3
- data/spec/requests/flows/authorization_code_spec.rb +34 -22
- data/spec/requests/flows/client_credentials_spec.rb +1 -1
- data/spec/requests/flows/password_spec.rb +32 -12
- data/spec/requests/flows/refresh_token_spec.rb +19 -19
- data/spec/requests/flows/revoke_token_spec.rb +18 -12
- data/spec/spec_helper.rb +1 -4
- data/spec/support/shared/controllers_shared_context.rb +33 -23
- data/spec/validators/redirect_uri_validator_spec.rb +1 -1
- metadata +6 -5
- data/spec/support/http_method_shim.rb +0 -29
|
@@ -40,6 +40,21 @@ module Doorkeeper
|
|
|
40
40
|
find_by_plaintext_token(:refresh_token, refresh_token)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
# Returns an instance of the Doorkeeper::AccessToken
|
|
44
|
+
# found by previous refresh token. Keep in mind that value
|
|
45
|
+
# of the previous_refresh_token isn't encrypted using
|
|
46
|
+
# secrets strategy.
|
|
47
|
+
#
|
|
48
|
+
# @param previous_refresh_token [#to_s]
|
|
49
|
+
# previous refresh token value (any object that responds to `#to_s`)
|
|
50
|
+
#
|
|
51
|
+
# @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
|
|
52
|
+
# if there is no record with such refresh token
|
|
53
|
+
#
|
|
54
|
+
def by_previous_refresh_token(previous_refresh_token)
|
|
55
|
+
find_by(refresh_token: previous_refresh_token)
|
|
56
|
+
end
|
|
57
|
+
|
|
43
58
|
# Revokes AccessToken records that have not been revoked and associated
|
|
44
59
|
# with the specific Application and Resource Owner.
|
|
45
60
|
#
|
|
@@ -49,10 +64,11 @@ module Doorkeeper
|
|
|
49
64
|
# instance of the Resource Owner model
|
|
50
65
|
#
|
|
51
66
|
def revoke_all_for(application_id, resource_owner, clock = Time)
|
|
52
|
-
where(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
where(
|
|
68
|
+
application_id: application_id,
|
|
69
|
+
resource_owner_id: resource_owner.id,
|
|
70
|
+
revoked_at: nil,
|
|
71
|
+
).update_all(revoked_at: clock.now.utc)
|
|
56
72
|
end
|
|
57
73
|
|
|
58
74
|
# Looking for not revoked Access Token with a matching set of scopes
|
|
@@ -142,8 +158,8 @@ module Doorkeeper
|
|
|
142
158
|
(token_scopes.sort == param_scopes.sort) &&
|
|
143
159
|
Doorkeeper::OAuth::Helpers::ScopeChecker.valid?(
|
|
144
160
|
scope_str: param_scopes.to_s,
|
|
145
|
-
server_scopes: Doorkeeper.
|
|
146
|
-
app_scopes: app_scopes
|
|
161
|
+
server_scopes: Doorkeeper.config.scopes,
|
|
162
|
+
app_scopes: app_scopes,
|
|
147
163
|
)
|
|
148
164
|
end
|
|
149
165
|
|
|
@@ -165,7 +181,7 @@ module Doorkeeper
|
|
|
165
181
|
# @return [Doorkeeper::AccessToken] existing record or a new one
|
|
166
182
|
#
|
|
167
183
|
def find_or_create_for(application, resource_owner_id, scopes, expires_in, use_refresh_token)
|
|
168
|
-
if Doorkeeper.
|
|
184
|
+
if Doorkeeper.config.reuse_access_token
|
|
169
185
|
access_token = matching_token_for(application, resource_owner_id, scopes)
|
|
170
186
|
|
|
171
187
|
return access_token if access_token&.reusable?
|
|
@@ -176,7 +192,7 @@ module Doorkeeper
|
|
|
176
192
|
resource_owner_id: resource_owner_id,
|
|
177
193
|
scopes: scopes.to_s,
|
|
178
194
|
expires_in: expires_in,
|
|
179
|
-
use_refresh_token: use_refresh_token
|
|
195
|
+
use_refresh_token: use_refresh_token,
|
|
180
196
|
)
|
|
181
197
|
end
|
|
182
198
|
|
|
@@ -191,10 +207,11 @@ module Doorkeeper
|
|
|
191
207
|
# @return [Doorkeeper::AccessToken] array of matching AccessToken objects
|
|
192
208
|
#
|
|
193
209
|
def authorized_tokens_for(application_id, resource_owner_id)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
210
|
+
where(
|
|
211
|
+
application_id: application_id,
|
|
212
|
+
resource_owner_id: resource_owner_id,
|
|
213
|
+
revoked_at: nil,
|
|
214
|
+
)
|
|
198
215
|
end
|
|
199
216
|
|
|
200
217
|
# Convenience method for backwards-compatibility, return the last
|
|
@@ -209,21 +226,22 @@ module Doorkeeper
|
|
|
209
226
|
# nil if nothing was found
|
|
210
227
|
#
|
|
211
228
|
def last_authorized_token_for(application_id, resource_owner_id)
|
|
212
|
-
authorized_tokens_for(application_id, resource_owner_id)
|
|
229
|
+
authorized_tokens_for(application_id, resource_owner_id)
|
|
230
|
+
.ordered_by(:created_at, :desc).first
|
|
213
231
|
end
|
|
214
232
|
|
|
215
233
|
##
|
|
216
234
|
# Determines the secret storing transformer
|
|
217
235
|
# Unless configured otherwise, uses the plain secret strategy
|
|
218
236
|
def secret_strategy
|
|
219
|
-
::Doorkeeper.
|
|
237
|
+
::Doorkeeper.config.token_secret_strategy
|
|
220
238
|
end
|
|
221
239
|
|
|
222
240
|
##
|
|
223
241
|
# Determine the fallback storing strategy
|
|
224
242
|
# Unless configured, there will be no fallback
|
|
225
243
|
def fallback_secret_strategy
|
|
226
|
-
::Doorkeeper.
|
|
244
|
+
::Doorkeeper.config.token_secret_fallback_strategy
|
|
227
245
|
end
|
|
228
246
|
end
|
|
229
247
|
|
|
@@ -300,8 +318,28 @@ module Doorkeeper
|
|
|
300
318
|
end
|
|
301
319
|
end
|
|
302
320
|
|
|
321
|
+
# Revokes token with `:refresh_token` equal to `:previous_refresh_token`
|
|
322
|
+
# and clears `:previous_refresh_token` attribute.
|
|
323
|
+
#
|
|
324
|
+
def revoke_previous_refresh_token!
|
|
325
|
+
return unless self.class.refresh_token_revoked_on_use?
|
|
326
|
+
|
|
327
|
+
old_refresh_token&.revoke
|
|
328
|
+
update_attribute :previous_refresh_token, ""
|
|
329
|
+
end
|
|
330
|
+
|
|
303
331
|
private
|
|
304
332
|
|
|
333
|
+
# Searches for Access Token record with `:refresh_token` equal to
|
|
334
|
+
# `:previous_refresh_token` value.
|
|
335
|
+
#
|
|
336
|
+
# @return [Doorkeeper::AccessToken, nil]
|
|
337
|
+
# Access Token record or nil if nothing found
|
|
338
|
+
#
|
|
339
|
+
def old_refresh_token
|
|
340
|
+
@old_refresh_token ||= self.class.by_previous_refresh_token(previous_refresh_token)
|
|
341
|
+
end
|
|
342
|
+
|
|
305
343
|
# Generates refresh token with UniqueToken generator.
|
|
306
344
|
#
|
|
307
345
|
# @return [String] refresh token value
|
|
@@ -312,7 +350,7 @@ module Doorkeeper
|
|
|
312
350
|
end
|
|
313
351
|
|
|
314
352
|
# Generates and sets the token value with the
|
|
315
|
-
# configured Generator class (see Doorkeeper.
|
|
353
|
+
# configured Generator class (see Doorkeeper.config).
|
|
316
354
|
#
|
|
317
355
|
# @return [String] generated token value
|
|
318
356
|
#
|
|
@@ -329,7 +367,7 @@ module Doorkeeper
|
|
|
329
367
|
scopes: scopes,
|
|
330
368
|
application: application,
|
|
331
369
|
expires_in: expires_in,
|
|
332
|
-
created_at: created_at
|
|
370
|
+
created_at: created_at,
|
|
333
371
|
)
|
|
334
372
|
|
|
335
373
|
secret_strategy.store_secret(self, :token, @raw_token)
|
|
@@ -337,7 +375,7 @@ module Doorkeeper
|
|
|
337
375
|
end
|
|
338
376
|
|
|
339
377
|
def token_generator
|
|
340
|
-
generator_name = Doorkeeper.
|
|
378
|
+
generator_name = Doorkeeper.config.access_token_generator
|
|
341
379
|
generator = generator_name.constantize
|
|
342
380
|
|
|
343
381
|
return generator if generator.respond_to?(:generate)
|
|
@@ -47,14 +47,14 @@ module Doorkeeper
|
|
|
47
47
|
# Determines the secret storing transformer
|
|
48
48
|
# Unless configured otherwise, uses the plain secret strategy
|
|
49
49
|
def secret_strategy
|
|
50
|
-
::Doorkeeper.
|
|
50
|
+
::Doorkeeper.config.application_secret_strategy
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
##
|
|
54
54
|
# Determine the fallback storing strategy
|
|
55
55
|
# Unless configured, there will be no fallback
|
|
56
56
|
def fallback_secret_strategy
|
|
57
|
-
::Doorkeeper.
|
|
57
|
+
::Doorkeeper.config.application_secret_fallback_strategy
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -72,7 +72,7 @@ module Doorkeeper
|
|
|
72
72
|
# @param input [#to_s] Plain secret provided by user
|
|
73
73
|
# (any object that responds to `#to_s`)
|
|
74
74
|
#
|
|
75
|
-
# @return [
|
|
75
|
+
# @return [Boolean] Whether the given secret matches the stored secret
|
|
76
76
|
# of this application.
|
|
77
77
|
#
|
|
78
78
|
def secret_matches?(input)
|
|
@@ -11,7 +11,7 @@ module Doorkeeper
|
|
|
11
11
|
return false if expired?
|
|
12
12
|
return true unless expires_in
|
|
13
13
|
|
|
14
|
-
threshold_limit = 100 - Doorkeeper.
|
|
14
|
+
threshold_limit = 100 - Doorkeeper.config.token_reuse_limit
|
|
15
15
|
expires_in_seconds >= threshold_limit * expires_in / 100
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -19,33 +19,6 @@ module Doorkeeper
|
|
|
19
19
|
def revoked?
|
|
20
20
|
!!(revoked_at && revoked_at <= Time.now.utc)
|
|
21
21
|
end
|
|
22
|
-
|
|
23
|
-
# Revokes token with `:refresh_token` equal to `:previous_refresh_token`
|
|
24
|
-
# and clears `:previous_refresh_token` attribute.
|
|
25
|
-
#
|
|
26
|
-
def revoke_previous_refresh_token!
|
|
27
|
-
return unless refresh_token_revoked_on_use?
|
|
28
|
-
|
|
29
|
-
old_refresh_token&.revoke
|
|
30
|
-
update_attribute :previous_refresh_token, ""
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
# Searches for Access Token record with `:refresh_token` equal to
|
|
36
|
-
# `:previous_refresh_token` value.
|
|
37
|
-
#
|
|
38
|
-
# @return [Doorkeeper::AccessToken, nil]
|
|
39
|
-
# Access Token record or nil if nothing found
|
|
40
|
-
#
|
|
41
|
-
def old_refresh_token
|
|
42
|
-
@old_refresh_token ||=
|
|
43
|
-
AccessToken.by_refresh_token(previous_refresh_token)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def refresh_token_revoked_on_use?
|
|
47
|
-
AccessToken.refresh_token_revoked_on_use?
|
|
48
|
-
end
|
|
49
22
|
end
|
|
50
23
|
end
|
|
51
24
|
end
|
|
@@ -12,7 +12,7 @@ module Doorkeeper
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def issue_token
|
|
15
|
-
@token ||=
|
|
15
|
+
@token ||= Doorkeeper.config.access_grant_model.create!(access_grant_attributes)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def oob_redirect
|
|
@@ -22,7 +22,7 @@ module Doorkeeper
|
|
|
22
22
|
private
|
|
23
23
|
|
|
24
24
|
def authorization_code_expires_in
|
|
25
|
-
Doorkeeper.
|
|
25
|
+
Doorkeeper.config.authorization_code_expires_in
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def access_grant_attributes
|
|
@@ -31,7 +31,7 @@ module Doorkeeper
|
|
|
31
31
|
resource_owner_id: resource_owner.id,
|
|
32
32
|
expires_in: authorization_code_expires_in,
|
|
33
33
|
redirect_uri: pre_auth.redirect_uri,
|
|
34
|
-
scopes: pre_auth.scopes.to_s
|
|
34
|
+
scopes: pre_auth.scopes.to_s,
|
|
35
35
|
)
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -47,7 +47,7 @@ module Doorkeeper
|
|
|
47
47
|
# Ensures firstly, if migration with additional PKCE columns was
|
|
48
48
|
# generated and migrated
|
|
49
49
|
def pkce_supported?
|
|
50
|
-
Doorkeeper
|
|
50
|
+
Doorkeeper.config.access_grant_model.pkce_supported?
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
end
|
|
@@ -19,7 +19,7 @@ module Doorkeeper
|
|
|
19
19
|
Doorkeeper::OAuth::Authorization::Context.new(
|
|
20
20
|
oauth_client,
|
|
21
21
|
grant_type,
|
|
22
|
-
scopes
|
|
22
|
+
scopes,
|
|
23
23
|
)
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -35,7 +35,7 @@ module Doorkeeper
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def refresh_token_enabled?(server, context)
|
|
38
|
-
if server.refresh_token_enabled?.respond_to?
|
|
38
|
+
if server.refresh_token_enabled?.respond_to?(:call)
|
|
39
39
|
server.refresh_token_enabled?.call(context)
|
|
40
40
|
else
|
|
41
41
|
!!server.refresh_token_enabled?
|
|
@@ -49,17 +49,20 @@ module Doorkeeper
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def issue_token
|
|
52
|
+
return @token if defined?(@token)
|
|
53
|
+
|
|
52
54
|
context = self.class.build_context(
|
|
53
55
|
pre_auth.client,
|
|
54
56
|
Doorkeeper::OAuth::IMPLICIT,
|
|
55
|
-
pre_auth.scopes
|
|
57
|
+
pre_auth.scopes,
|
|
56
58
|
)
|
|
57
|
-
|
|
59
|
+
|
|
60
|
+
@token = configuration.access_token_model.find_or_create_for(
|
|
58
61
|
pre_auth.client,
|
|
59
62
|
resource_owner.id,
|
|
60
63
|
pre_auth.scopes,
|
|
61
64
|
self.class.access_token_expires_in(configuration, context),
|
|
62
|
-
false
|
|
65
|
+
false,
|
|
63
66
|
)
|
|
64
67
|
end
|
|
65
68
|
|
|
@@ -74,7 +77,7 @@ module Doorkeeper
|
|
|
74
77
|
private
|
|
75
78
|
|
|
76
79
|
def configuration
|
|
77
|
-
Doorkeeper.
|
|
80
|
+
Doorkeeper.config
|
|
78
81
|
end
|
|
79
82
|
|
|
80
83
|
def controller
|
|
@@ -32,10 +32,13 @@ module Doorkeeper
|
|
|
32
32
|
raise Errors::InvalidGrantReuse if grant.revoked?
|
|
33
33
|
|
|
34
34
|
grant.revoke
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
|
|
36
|
+
find_or_create_access_token(
|
|
37
|
+
grant.application,
|
|
38
|
+
grant.resource_owner_id,
|
|
39
|
+
grant.scopes,
|
|
40
|
+
server,
|
|
41
|
+
)
|
|
39
42
|
end
|
|
40
43
|
super
|
|
41
44
|
end
|
|
@@ -71,7 +74,7 @@ module Doorkeeper
|
|
|
71
74
|
def validate_redirect_uri
|
|
72
75
|
Helpers::URIChecker.valid_for_authorization?(
|
|
73
76
|
redirect_uri,
|
|
74
|
-
grant.redirect_uri
|
|
77
|
+
grant.redirect_uri,
|
|
75
78
|
)
|
|
76
79
|
end
|
|
77
80
|
|
|
@@ -82,13 +85,17 @@ module Doorkeeper
|
|
|
82
85
|
return false unless grant.pkce_supported?
|
|
83
86
|
|
|
84
87
|
if grant.code_challenge_method == "S256"
|
|
85
|
-
grant.code_challenge ==
|
|
88
|
+
grant.code_challenge == generate_code_challenge(code_verifier)
|
|
86
89
|
elsif grant.code_challenge_method == "plain"
|
|
87
90
|
grant.code_challenge == code_verifier
|
|
88
91
|
else
|
|
89
92
|
false
|
|
90
93
|
end
|
|
91
94
|
end
|
|
95
|
+
|
|
96
|
+
def generate_code_challenge(code_verifier)
|
|
97
|
+
server_config.access_grant_model.generate_code_challenge(code_verifier)
|
|
98
|
+
end
|
|
92
99
|
end
|
|
93
100
|
end
|
|
94
101
|
end
|
|
@@ -36,21 +36,25 @@ module Doorkeeper
|
|
|
36
36
|
|
|
37
37
|
def find_or_create_access_token(client, resource_owner_id, scopes, server)
|
|
38
38
|
context = Authorization::Token.build_context(client, grant_type, scopes)
|
|
39
|
-
@access_token =
|
|
39
|
+
@access_token = server_config.access_token_model.find_or_create_for(
|
|
40
40
|
client,
|
|
41
41
|
resource_owner_id,
|
|
42
42
|
scopes,
|
|
43
43
|
Authorization::Token.access_token_expires_in(server, context),
|
|
44
|
-
Authorization::Token.refresh_token_enabled?(server, context)
|
|
44
|
+
Authorization::Token.refresh_token_enabled?(server, context),
|
|
45
45
|
)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def before_successful_response
|
|
49
|
-
|
|
49
|
+
server_config.before_successful_strategy_response.call(self)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def after_successful_response
|
|
53
|
-
|
|
53
|
+
server_config.after_successful_strategy_response.call(self, @response)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def server_config
|
|
57
|
+
Doorkeeper.config
|
|
54
58
|
end
|
|
55
59
|
|
|
56
60
|
private
|
|
@@ -11,18 +11,17 @@ module Doorkeeper
|
|
|
11
11
|
@application = application
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def self.find(uid, method =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
def self.find(uid, method = Doorkeeper.config.application_model.method(:by_uid))
|
|
15
|
+
return unless (application = method.call(uid))
|
|
16
|
+
|
|
17
|
+
new(application)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def self.authenticate(credentials, method =
|
|
20
|
+
def self.authenticate(credentials, method = Doorkeeper.config.application_model.method(:by_uid_and_secret))
|
|
21
21
|
return if credentials.blank?
|
|
22
|
+
return unless (application = method.call(credentials.uid, credentials.secret))
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
new(application)
|
|
25
|
-
end
|
|
24
|
+
new(application)
|
|
26
25
|
end
|
|
27
26
|
end
|
|
28
27
|
end
|
|
@@ -5,24 +5,31 @@ module Doorkeeper
|
|
|
5
5
|
class ClientCredentialsRequest < BaseRequest
|
|
6
6
|
class Creator
|
|
7
7
|
def call(client, scopes, attributes = {})
|
|
8
|
-
|
|
8
|
+
if lookup_existing_token?
|
|
9
|
+
existing_token = find_existing_token_for(client, scopes)
|
|
10
|
+
return existing_token if server_config.reuse_access_token && existing_token&.reusable?
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
return existing_token
|
|
12
|
+
existing_token&.revoke if server_config.revoke_previous_client_credentials_token
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
AccessToken.find_or_create_for(
|
|
15
|
+
server_config.access_token_model.find_or_create_for(
|
|
17
16
|
client, nil, scopes, attributes[:expires_in],
|
|
18
|
-
attributes[:use_refresh_token]
|
|
17
|
+
attributes[:use_refresh_token],
|
|
19
18
|
)
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
private
|
|
23
22
|
|
|
24
|
-
def
|
|
25
|
-
|
|
23
|
+
def lookup_existing_token?
|
|
24
|
+
server_config.reuse_access_token || server_config.revoke_previous_client_credentials_token
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def find_existing_token_for(client, scopes)
|
|
28
|
+
server_config.access_token_model.matching_token_for(client, nil, scopes)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def server_config
|
|
32
|
+
Doorkeeper.config
|
|
26
33
|
end
|
|
27
34
|
end
|
|
28
35
|
end
|
|
@@ -4,20 +4,20 @@ module Doorkeeper
|
|
|
4
4
|
module OAuth
|
|
5
5
|
class ClientCredentialsRequest < BaseRequest
|
|
6
6
|
class Issuer
|
|
7
|
-
attr_accessor :token, :
|
|
7
|
+
attr_accessor :token, :validator, :error
|
|
8
8
|
|
|
9
|
-
def initialize(server,
|
|
9
|
+
def initialize(server, validator)
|
|
10
10
|
@server = server
|
|
11
|
-
@
|
|
11
|
+
@validator = validator
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def create(client, scopes, creator = Creator.new)
|
|
15
|
-
if
|
|
15
|
+
if validator.valid?
|
|
16
16
|
@token = create_token(client, scopes, creator)
|
|
17
17
|
@error = :server_error unless @token
|
|
18
18
|
else
|
|
19
19
|
@token = false
|
|
20
|
-
@error =
|
|
20
|
+
@error = validator.error
|
|
21
21
|
end
|
|
22
22
|
@token
|
|
23
23
|
end
|
|
@@ -28,7 +28,7 @@ module Doorkeeper
|
|
|
28
28
|
context = Authorization::Token.build_context(
|
|
29
29
|
client,
|
|
30
30
|
Doorkeeper::OAuth::CLIENT_CREDENTIALS,
|
|
31
|
-
scopes
|
|
31
|
+
scopes,
|
|
32
32
|
)
|
|
33
33
|
ttl = Authorization::Token.access_token_expires_in(@server, context)
|
|
34
34
|
|
|
@@ -36,7 +36,7 @@ module Doorkeeper
|
|
|
36
36
|
client,
|
|
37
37
|
scopes,
|
|
38
38
|
use_refresh_token: false,
|
|
39
|
-
expires_in: ttl
|
|
39
|
+
expires_in: ttl,
|
|
40
40
|
)
|
|
41
41
|
end
|
|
42
42
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
module OAuth
|
|
5
5
|
class ClientCredentialsRequest < BaseRequest
|
|
6
|
-
class
|
|
6
|
+
class Validator
|
|
7
7
|
include Validations
|
|
8
8
|
include OAuth::Helpers
|
|
9
9
|
|
|
@@ -26,9 +26,9 @@ module Doorkeeper
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def validate_client_supports_grant_flow
|
|
29
|
-
Doorkeeper.
|
|
29
|
+
Doorkeeper.config.allow_grant_flow_for_client?(
|
|
30
30
|
Doorkeeper::OAuth::CLIENT_CREDENTIALS,
|
|
31
|
-
@client
|
|
31
|
+
@client,
|
|
32
32
|
)
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -45,7 +45,7 @@ module Doorkeeper
|
|
|
45
45
|
scope_str: @request.scopes.to_s,
|
|
46
46
|
server_scopes: @server.scopes,
|
|
47
47
|
app_scopes: application_scopes,
|
|
48
|
-
grant_type: Doorkeeper::OAuth::CLIENT_CREDENTIALS
|
|
48
|
+
grant_type: Doorkeeper::OAuth::CLIENT_CREDENTIALS,
|
|
49
49
|
)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
@@ -26,13 +26,13 @@ module Doorkeeper
|
|
|
26
26
|
access_token: auth.token.plaintext_token,
|
|
27
27
|
token_type: auth.token.token_type,
|
|
28
28
|
expires_in: auth.token.expires_in_seconds,
|
|
29
|
-
state: pre_auth.state
|
|
29
|
+
state: pre_auth.state,
|
|
30
30
|
)
|
|
31
31
|
else
|
|
32
32
|
Authorization::URIBuilder.uri_with_query(
|
|
33
33
|
pre_auth.redirect_uri,
|
|
34
34
|
code: auth.token.plaintext_token,
|
|
35
|
-
state: pre_auth.state
|
|
35
|
+
state: pre_auth.state,
|
|
36
36
|
)
|
|
37
37
|
end
|
|
38
38
|
end
|
|
@@ -10,8 +10,8 @@ module Doorkeeper
|
|
|
10
10
|
attributes.merge(
|
|
11
11
|
name: request.error,
|
|
12
12
|
state: request.try(:state),
|
|
13
|
-
redirect_uri: request.try(:redirect_uri)
|
|
14
|
-
)
|
|
13
|
+
redirect_uri: request.try(:redirect_uri),
|
|
14
|
+
),
|
|
15
15
|
)
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -46,9 +46,9 @@ module Doorkeeper
|
|
|
46
46
|
|
|
47
47
|
def redirect_uri
|
|
48
48
|
if @response_on_fragment
|
|
49
|
-
Authorization::URIBuilder.uri_with_fragment
|
|
49
|
+
Authorization::URIBuilder.uri_with_fragment(@redirect_uri, body)
|
|
50
50
|
else
|
|
51
|
-
Authorization::URIBuilder.uri_with_query
|
|
51
|
+
Authorization::URIBuilder.uri_with_query(@redirect_uri, body)
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
@@ -70,7 +70,7 @@ module Doorkeeper
|
|
|
70
70
|
delegate :realm, to: :configuration
|
|
71
71
|
|
|
72
72
|
def configuration
|
|
73
|
-
Doorkeeper.
|
|
73
|
+
Doorkeeper.config
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def exception_class
|
|
@@ -13,7 +13,7 @@ module Doorkeeper
|
|
|
13
13
|
@valid_scopes = valid_scopes(server_scopes, app_scopes)
|
|
14
14
|
|
|
15
15
|
if grant_type
|
|
16
|
-
@scopes_by_grant_type = Doorkeeper.
|
|
16
|
+
@scopes_by_grant_type = Doorkeeper.config.scopes_by_grant_type[grant_type.to_sym]
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -43,10 +43,12 @@ module Doorkeeper
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def self.valid?(scope_str:, server_scopes:, app_scopes: nil, grant_type: nil)
|
|
46
|
-
Validator.new(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
Validator.new(
|
|
47
|
+
scope_str,
|
|
48
|
+
server_scopes,
|
|
49
|
+
app_scopes,
|
|
50
|
+
grant_type,
|
|
51
|
+
).valid?
|
|
50
52
|
end
|
|
51
53
|
end
|
|
52
54
|
end
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
module OAuth
|
|
5
5
|
module Helpers
|
|
6
|
+
# Default Doorkeeper token generator. Follows OAuth RFC and
|
|
7
|
+
# could be customized using `default_generator_method` in
|
|
8
|
+
# configuration.
|
|
6
9
|
module UniqueToken
|
|
7
10
|
def self.generate(options = {})
|
|
8
11
|
# Access Token value must be 1*VSCHAR or
|
|
@@ -11,15 +14,15 @@ module Doorkeeper
|
|
|
11
14
|
# @see https://tools.ietf.org/html/rfc6749#appendix-A.12
|
|
12
15
|
# @see https://tools.ietf.org/html/rfc6750#section-2.1
|
|
13
16
|
#
|
|
14
|
-
|
|
15
|
-
token_size
|
|
16
|
-
|
|
17
|
+
generator = options.delete(:generator) || SecureRandom.method(default_generator_method)
|
|
18
|
+
token_size = options.delete(:size) || 32
|
|
19
|
+
generator.call(token_size)
|
|
17
20
|
end
|
|
18
21
|
|
|
19
22
|
# Generator method for default generator class (SecureRandom)
|
|
20
23
|
#
|
|
21
|
-
def self.
|
|
22
|
-
Doorkeeper.
|
|
24
|
+
def self.default_generator_method
|
|
25
|
+
Doorkeeper.config.default_generator_method
|
|
23
26
|
end
|
|
24
27
|
end
|
|
25
28
|
end
|