doorkeeper 5.6.4 → 5.6.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1f7bb9a1bb5e08c4b7c3ccb920bef61fbbd1dc0b11f76bba3a3d76a6fc8eeed
4
- data.tar.gz: 456ffe74dac831f3b797565041e46ecf241fb4cfc597d0bc39aa7a3893abeecb
3
+ metadata.gz: 8430b36ebe602cb716e1d404c53e17cbe41a6e122fb3004e77dc5b16ea70a7bd
4
+ data.tar.gz: 7d8033e2051e21776c0d57e3bbe23d6d2cea04e615c48b9d82a7a704373ff7cb
5
5
  SHA512:
6
- metadata.gz: 6e23087c44495ce91c7e23f1bf8cd771dc82bdb92ffa1cac8f8bef2e42919bf8eea1ac86b1ed76580537c4b5a6b2ba571452470677259fb61e4be0e151091ad7
7
- data.tar.gz: fcafc844c46bab18f03d5dd7e8bd345111fb57530275adbf8d9954f8e8c1436b29ded79e15f6321e9f86c845836b713c65aca23398114cfdb5c77e9b87a01647
6
+ metadata.gz: a89cf897778ebd53736ff57f9e7f5eb587ffa6da110e04a62a99816b3719ab9d109700a6cace1d36208bfb34eeb4fd7153aeaef7792275b57cde34e189904510
7
+ data.tar.gz: bc943f37ca582f1badaa25d98715f1e5ec2a86f8da3f99ef7367cbcc63a99a20a0cc3458d1c2919bb1088e6a09ffd47e33a6634b78b8fcc0e49993681c56a683
data/CHANGELOG.md CHANGED
@@ -9,6 +9,12 @@ User-visible changes worth mentioning.
9
9
 
10
10
  - [#ID] Add your PR description here.
11
11
 
12
+ # 5.6.5
13
+
14
+ - [#1602] Allow custom data to be stored inside access grants/tokens.
15
+ - [#1634] Code refactoring for custom token attributes.
16
+ - [#1639] Add grant type validation to avoid Internal Server Error for DELETE /oauth/authorize endpoint.
17
+
12
18
  # 5.6.4
13
19
 
14
20
  - [#1633] Apply ORM configuration in #to_prepare block to avoid autoloading errors.
@@ -13,11 +13,19 @@ module Doorkeeper
13
13
  end
14
14
 
15
15
  def create
16
- redirect_or_render authorize_response
16
+ redirect_or_render(authorize_response)
17
17
  end
18
18
 
19
19
  def destroy
20
- redirect_or_render authorization.deny
20
+ redirect_or_render(authorization.deny)
21
+ rescue Doorkeeper::Errors::InvalidTokenStrategy => e
22
+ error_response = get_error_response_from_exception(e)
23
+
24
+ if Doorkeeper.configuration.api_only
25
+ render json: error_response.body, status: :bad_request
26
+ else
27
+ render :error, locals: { error_response: error_response }
28
+ end
21
29
  end
22
30
 
23
31
  private
@@ -37,7 +45,7 @@ module Doorkeeper
37
45
  render json: pre_auth.error_response.body,
38
46
  status: :bad_request
39
47
  else
40
- render :error
48
+ render :error, locals: { error_response: pre_auth.error_response }
41
49
  end
42
50
  end
43
51
 
@@ -88,7 +96,7 @@ module Doorkeeper
88
96
  end
89
97
 
90
98
  def pre_auth_param_fields
91
- %i[
99
+ custom_access_token_attributes + %i[
92
100
  client_id
93
101
  code_challenge
94
102
  code_challenge_method
@@ -100,6 +108,10 @@ module Doorkeeper
100
108
  ]
101
109
  end
102
110
 
111
+ def custom_access_token_attributes
112
+ Doorkeeper.config.custom_access_token_attributes.map(&:to_sym)
113
+ end
114
+
103
115
  def authorization
104
116
  @authorization ||= strategy.request
105
117
  end
@@ -3,5 +3,7 @@
3
3
  </div>
4
4
 
5
5
  <main role="main">
6
- <pre><%= @pre_auth.error_response.body[:error_description] %></pre>
6
+ <pre>
7
+ <%= (respond_to?(:error_response) ? error_response : @pre_auth.error_response).body[:error_description] %>
8
+ </pre>
7
9
  </main>
@@ -11,6 +11,7 @@ module Doorkeeper
11
11
  validate_reuse_access_token_value
12
12
  validate_token_reuse_limit
13
13
  validate_secret_strategies
14
+ validate_custom_access_token_attributes
14
15
  end
15
16
 
16
17
  private
@@ -48,6 +49,20 @@ module Doorkeeper
48
49
  )
49
50
  @token_reuse_limit = 100
50
51
  end
52
+
53
+ # Validate that the access_token and access_grant models
54
+ # both respond to all of the custom attributes
55
+ def validate_custom_access_token_attributes
56
+ return if custom_access_token_attributes.blank?
57
+
58
+ custom_access_token_attributes.each do |attribute_name|
59
+ [access_token_model, access_grant_model].each do |model|
60
+ next if model.has_attribute?(attribute_name)
61
+
62
+ raise Doorkeeper::Errors::ConfigError, "#{model} does not recognize custom attribute: #{attribute_name}."
63
+ end
64
+ end
65
+ end
51
66
  end
52
67
  end
53
68
  end
@@ -321,6 +321,15 @@ module Doorkeeper
321
321
  option :access_token_generator,
322
322
  default: "Doorkeeper::OAuth::Helpers::UniqueToken"
323
323
 
324
+ # Allows additional data to be received when granting access to an Application, and for this
325
+ # additional data to be sent with subsequently generated access tokens. The access grant and
326
+ # access token models will both need to respond to the specified attribute names.
327
+ #
328
+ # @param attributes [Array] The array of custom attribute names to be saved
329
+ #
330
+ option :custom_access_token_attributes,
331
+ default: []
332
+
324
333
  # Use a custom class for generating the application secret.
325
334
  # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-application-secret-generator
326
335
  #
@@ -44,6 +44,7 @@ module Doorkeeper
44
44
  UnableToGenerateToken = Class.new(DoorkeeperError)
45
45
  TokenGeneratorNotFound = Class.new(DoorkeeperError)
46
46
  NoOrmCleaner = Class.new(DoorkeeperError)
47
+ ConfigError = Class.new(DoorkeeperError)
47
48
 
48
49
  InvalidToken = Class.new(BaseResponseError)
49
50
  TokenExpired = Class.new(InvalidToken)
@@ -45,7 +45,13 @@ module Doorkeeper
45
45
  attributes[:resource_owner_id] = resource_owner.id
46
46
  end
47
47
 
48
- pkce_attributes.merge(attributes)
48
+ pkce_attributes.merge(attributes).merge(custom_attributes)
49
+ end
50
+
51
+ def custom_attributes
52
+ # Custom access token attributes are saved into the access grant,
53
+ # and then included in subsequently generated access tokens.
54
+ @pre_auth.custom_access_token_attributes.to_h.with_indifferent_access
49
55
  end
50
56
 
51
57
  def pkce_attributes
@@ -35,6 +35,7 @@ module Doorkeeper
35
35
  grant.application,
36
36
  resource_owner,
37
37
  grant.scopes,
38
+ custom_token_attributes_with_data,
38
39
  server,
39
40
  )
40
41
  end
@@ -55,11 +56,12 @@ module Doorkeeper
55
56
  end
56
57
 
57
58
  def validate_params
58
- @missing_param = if grant&.uses_pkce? && code_verifier.blank?
59
- :code_verifier
60
- elsif redirect_uri.blank?
61
- :redirect_uri
62
- end
59
+ @missing_param =
60
+ if grant&.uses_pkce? && code_verifier.blank?
61
+ :code_verifier
62
+ elsif redirect_uri.blank?
63
+ :redirect_uri
64
+ end
63
65
 
64
66
  @missing_param.nil?
65
67
  end
@@ -97,7 +99,15 @@ module Doorkeeper
97
99
  end
98
100
 
99
101
  def generate_code_challenge(code_verifier)
100
- server_config.access_grant_model.generate_code_challenge(code_verifier)
102
+ Doorkeeper.config.access_grant_model.generate_code_challenge(code_verifier)
103
+ end
104
+
105
+ def custom_token_attributes_with_data
106
+ grant
107
+ .attributes
108
+ .with_indifferent_access
109
+ .slice(*Doorkeeper.config.custom_access_token_attributes)
110
+ .symbolize_keys
101
111
  end
102
112
  end
103
113
  end
@@ -26,27 +26,28 @@ module Doorkeeper
26
26
  @scopes ||= build_scopes
27
27
  end
28
28
 
29
- def find_or_create_access_token(client, resource_owner, scopes, server)
29
+ def find_or_create_access_token(client, resource_owner, scopes, custom_attributes, server)
30
30
  context = Authorization::Token.build_context(client, grant_type, scopes, resource_owner)
31
- @access_token = server_config.access_token_model.find_or_create_for(
32
- application: client.is_a?(server_config.application_model) ? client : client&.application,
31
+ application = client.is_a?(Doorkeeper.config.application_model) ? client : client&.application
32
+
33
+ token_attributes = {
34
+ application: application,
33
35
  resource_owner: resource_owner,
34
36
  scopes: scopes,
35
37
  expires_in: Authorization::Token.access_token_expires_in(server, context),
36
38
  use_refresh_token: Authorization::Token.refresh_token_enabled?(server, context),
37
- )
39
+ }
40
+
41
+ @access_token =
42
+ Doorkeeper.config.access_token_model.find_or_create_for(**token_attributes.merge(custom_attributes))
38
43
  end
39
44
 
40
45
  def before_successful_response
41
- server_config.before_successful_strategy_response.call(self)
46
+ Doorkeeper.config.before_successful_strategy_response.call(self)
42
47
  end
43
48
 
44
49
  def after_successful_response
45
- server_config.after_successful_strategy_response.call(self, @response)
46
- end
47
-
48
- def server_config
49
- Doorkeeper.config
50
+ Doorkeeper.config.after_successful_strategy_response.call(self, @response)
50
51
  end
51
52
 
52
53
  private
@@ -9,12 +9,12 @@ module Doorkeeper
9
9
 
10
10
  if lookup_existing_token?
11
11
  existing_token = find_active_existing_token_for(client, scopes)
12
- return existing_token if server_config.reuse_access_token && existing_token&.reusable?
12
+ return existing_token if Doorkeeper.config.reuse_access_token && existing_token&.reusable?
13
13
  end
14
14
 
15
15
  with_revocation(existing_token: existing_token) do
16
- application = client.is_a?(server_config.application_model) ? client : client&.application
17
- server_config.access_token_model.create_for(
16
+ application = client.is_a?(Doorkeeper.config.application_model) ? client : client&.application
17
+ Doorkeeper.config.access_token_model.create_for(
18
18
  application: application,
19
19
  resource_owner: nil,
20
20
  scopes: scopes,
@@ -26,7 +26,7 @@ module Doorkeeper
26
26
  private
27
27
 
28
28
  def with_revocation(existing_token:)
29
- if existing_token && server_config.revoke_previous_client_credentials_token?
29
+ if existing_token && Doorkeeper.config.revoke_previous_client_credentials_token?
30
30
  existing_token.with_lock do
31
31
  raise Errors::DoorkeeperError, :invalid_token_reuse if existing_token.revoked?
32
32
 
@@ -40,16 +40,12 @@ module Doorkeeper
40
40
  end
41
41
 
42
42
  def lookup_existing_token?
43
- server_config.reuse_access_token ||
44
- server_config.revoke_previous_client_credentials_token?
43
+ Doorkeeper.config.reuse_access_token ||
44
+ Doorkeeper.config.revoke_previous_client_credentials_token?
45
45
  end
46
46
 
47
47
  def find_active_existing_token_for(client, scopes)
48
- server_config.access_token_model.matching_token_for(client, nil, scopes, include_expired: false)
49
- end
50
-
51
- def server_config
52
- Doorkeeper.config
48
+ Doorkeeper.config.access_token_model.matching_token_for(client, nil, scopes, include_expired: false)
53
49
  end
54
50
  end
55
51
  end
@@ -25,7 +25,7 @@ module Doorkeeper
25
25
  private
26
26
 
27
27
  def before_successful_response
28
- find_or_create_access_token(client, resource_owner, scopes, server)
28
+ find_or_create_access_token(client, resource_owner, scopes, {}, server)
29
29
  super
30
30
  end
31
31
 
@@ -68,7 +68,7 @@ module Doorkeeper
68
68
  end
69
69
 
70
70
  def validate_client_supports_grant_flow
71
- server_config.allow_grant_flow_for_client?(grant_type, client&.application)
71
+ Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client&.application)
72
72
  end
73
73
  end
74
74
  end
@@ -18,19 +18,20 @@ module Doorkeeper
18
18
 
19
19
  attr_reader :client, :code_challenge, :code_challenge_method, :missing_param,
20
20
  :redirect_uri, :resource_owner, :response_type, :state,
21
- :authorization_response_flow, :response_mode
21
+ :authorization_response_flow, :response_mode, :custom_access_token_attributes
22
22
 
23
23
  def initialize(server, parameters = {}, resource_owner = nil)
24
- @server = server
25
- @client_id = parameters[:client_id]
26
- @response_type = parameters[:response_type]
27
- @response_mode = parameters[:response_mode]
28
- @redirect_uri = parameters[:redirect_uri]
29
- @scope = parameters[:scope]
30
- @state = parameters[:state]
31
- @code_challenge = parameters[:code_challenge]
24
+ @server = server
25
+ @client_id = parameters[:client_id]
26
+ @response_type = parameters[:response_type]
27
+ @response_mode = parameters[:response_mode]
28
+ @redirect_uri = parameters[:redirect_uri]
29
+ @scope = parameters[:scope]
30
+ @state = parameters[:state]
31
+ @code_challenge = parameters[:code_challenge]
32
32
  @code_challenge_method = parameters[:code_challenge_method]
33
- @resource_owner = resource_owner
33
+ @resource_owner = resource_owner
34
+ @custom_access_token_attributes = parameters.slice(*Doorkeeper.config.custom_access_token_attributes)
34
35
  end
35
36
 
36
37
  def authorizable?
@@ -26,7 +26,7 @@ module Doorkeeper
26
26
  private
27
27
 
28
28
  def load_client(credentials)
29
- server_config.application_model.by_uid_and_secret(credentials.uid, credentials.secret)
29
+ Doorkeeper.config.application_model.by_uid_and_secret(credentials.uid, credentials.secret)
30
30
  end
31
31
 
32
32
  def before_successful_response
@@ -41,7 +41,7 @@ module Doorkeeper
41
41
  end
42
42
 
43
43
  def refresh_token_revoked_on_use?
44
- server_config.access_token_model.refresh_token_revoked_on_use?
44
+ Doorkeeper.config.access_token_model.refresh_token_revoked_on_use?
45
45
  end
46
46
 
47
47
  def default_scopes
@@ -75,7 +75,7 @@ module Doorkeeper
75
75
  # Here we assume that TTL of the token received after refreshing should be
76
76
  # the same as that of the original token.
77
77
  #
78
- @access_token = server_config.access_token_model.create_for(
78
+ @access_token = Doorkeeper.config.access_token_model.create_for(
79
79
  application: refresh_token.application,
80
80
  resource_owner: resource_owner,
81
81
  scopes: scopes,
@@ -5,7 +5,7 @@ module Doorkeeper
5
5
  # Semantic versioning
6
6
  MAJOR = 5
7
7
  MINOR = 6
8
- TINY = 4
8
+ TINY = 5
9
9
  PRE = nil
10
10
 
11
11
  # Full version number
@@ -391,6 +391,23 @@ Doorkeeper.configure do
391
391
  # resource_owner.admin? || client.owners_allowlist.include?(resource_owner)
392
392
  # end
393
393
 
394
+ # Allows additional data fields to be sent while granting access to an application,
395
+ # and for this additional data to be included in subsequently generated access tokens.
396
+ # The 'authorizations/new' page will need to be overridden to include this additional data
397
+ # in the request params when granting access. The access grant and access token models
398
+ # will both need to respond to these additional data fields, and have a database column
399
+ # to store them in.
400
+ #
401
+ # Example:
402
+ # You have a multi-tenanted platform and want to be able to grant access to a specific
403
+ # tenant, rather than all the tenants a user has access to. You can use this config
404
+ # option to specify that a ':tenant_id' will be passed when authorizing. This tenant_id
405
+ # will be included in the access tokens. When a request is made with one of these access
406
+ # tokens, you can check that the requested data belongs to the specified tenant.
407
+ #
408
+ # Default value is an empty Array: []
409
+ # custom_access_token_attributes [:tenant_id]
410
+
394
411
  # Hook into the strategies' request & response life-cycle in case your
395
412
  # application needs advanced customization or logging:
396
413
  #
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.6.4
4
+ version: 5.6.5
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: 2023-01-31 00:00:00.000000000 Z
14
+ date: 2023-02-22 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: railties