doorkeeper 5.6.6 → 5.6.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b62a0472a97d06b40362817c9d5c0dd7dd6e0d0e600437a19f5cf2fd18c4be46
4
- data.tar.gz: 9850cef14c21a1f0df2fb451a485ab5b8066360a3008124f7aed287409364e36
3
+ metadata.gz: b8a202451362fe346d53be4d16dcb92fea331ee1aad93461283585f93749960b
4
+ data.tar.gz: 2f042a729cdd68ce19d6181a54a98635715f83e93946de95b62a7521400d4951
5
5
  SHA512:
6
- metadata.gz: de0c7021c4735b26249e5b267db11ede06f55b23d8f9bd51641d1cf3eee3812e14a2deec986e8aa6ee81de98097083fdb634a441fd4928cb47286fa977ba5d96
7
- data.tar.gz: 3865639c837771ceeafceec8a110e506f88fef45c61f7274782c637e794f9185be18ee98270852bac6fecb0fc90e4893dfed08d715c761507e87396e5a559bc2
6
+ metadata.gz: ab8dab957c6cfa382f406c465a187b3d1301a38eac8666789ad87755f2f383cb7f6a0f10f5b18f15dd4cbe5bb80f41697d01486d58739c5fca342c13a1bfe196
7
+ data.tar.gz: c0490f4072de798755643890309ff8d2ff645a5fa00797e2f5c933c6f1ffa685190cb935b2569a26fff5d282d3efd34f544b8784f598b8228c01259e784fe63b
data/CHANGELOG.md CHANGED
@@ -7,7 +7,20 @@ User-visible changes worth mentioning.
7
7
 
8
8
  ## main
9
9
 
10
- - [#ID] Add your PR description here.
10
+ - [#PR ID] Add your changelog here.
11
+
12
+ ## 5.6.8
13
+
14
+ - [#1680] Fix handle_auth_errors :raise NotImplementedError
15
+
16
+ ## 5.6.7
17
+
18
+ - [#1662] Specify uri_redirect validation class explicitly.
19
+ - [#1652] Add custom attributes support to token generator.
20
+ - [#1667] Pass `client` instead of `grant.application` to `find_or_create_access_token`.
21
+ - [#1673] Honor `custom_access_token_attributes` in client credentials grant flow.
22
+ - [#1676] Improve AuthorizationsController error response handling
23
+ - [#1677] Fix URIHelper.valid_for_authorization? breaking for non url URIs.
11
24
 
12
25
  ## 5.6.6
13
26
 
@@ -41,11 +41,14 @@ module Doorkeeper
41
41
  end
42
42
 
43
43
  def render_error
44
- if Doorkeeper.configuration.api_only
45
- render json: pre_auth.error_response.body,
46
- status: :bad_request
44
+ pre_auth.error_response.raise_exception! if Doorkeeper.config.raise_on_errors?
45
+
46
+ if Doorkeeper.configuration.redirect_on_errors? && pre_auth.error_response.redirectable?
47
+ redirect_or_render(pre_auth.error_response)
48
+ elsif Doorkeeper.configuration.api_only
49
+ render json: pre_auth.error_response.body, status: pre_auth.error_response.status
47
50
  else
48
- render :error, locals: { error_response: pre_auth.error_response }
51
+ render :error, locals: { error_response: pre_auth.error_response }, status: pre_auth.error_response.status
49
52
  end
50
53
  end
51
54
 
@@ -501,6 +501,10 @@ module Doorkeeper
501
501
  handle_auth_errors == :raise
502
502
  end
503
503
 
504
+ def redirect_on_errors?
505
+ handle_auth_errors == :redirect
506
+ end
507
+
504
508
  def application_secret_hashed?
505
509
  instance_variable_defined?(:"@application_secret_strategy")
506
510
  end
@@ -39,13 +39,31 @@ module Doorkeeper
39
39
  def initialize(response)
40
40
  @response = response
41
41
  end
42
+
43
+ def self.name_for_response
44
+ self.name.demodulize.underscore.to_sym
45
+ end
42
46
  end
43
47
 
44
48
  UnableToGenerateToken = Class.new(DoorkeeperError)
45
49
  TokenGeneratorNotFound = Class.new(DoorkeeperError)
46
50
  NoOrmCleaner = Class.new(DoorkeeperError)
47
51
 
52
+ InvalidRequest = Class.new(BaseResponseError)
48
53
  InvalidToken = Class.new(BaseResponseError)
54
+ InvalidClient = Class.new(BaseResponseError)
55
+ InvalidScope = Class.new(BaseResponseError)
56
+ InvalidRedirectUri = Class.new(BaseResponseError)
57
+ InvalidCodeChallengeMethod = Class.new(BaseResponseError)
58
+ InvalidGrant = Class.new(BaseResponseError)
59
+
60
+ UnauthorizedClient = Class.new(BaseResponseError)
61
+ UnsupportedResponseType = Class.new(BaseResponseError)
62
+ UnsupportedResponseMode = Class.new(BaseResponseError)
63
+
64
+ AccessDenied = Class.new(BaseResponseError)
65
+ ServerError = Class.new(BaseResponseError)
66
+
49
67
  TokenExpired = Class.new(InvalidToken)
50
68
  TokenRevoked = Class.new(InvalidToken)
51
69
  TokenUnknown = Class.new(InvalidToken)
@@ -435,6 +435,10 @@ module Doorkeeper
435
435
  if Doorkeeper.config.polymorphic_resource_owner?
436
436
  attributes[:resource_owner] = resource_owner
437
437
  end
438
+
439
+ Doorkeeper.config.custom_access_token_attributes.each do |attribute_name|
440
+ attributes[attribute_name] = public_send(attribute_name)
441
+ end
438
442
  end
439
443
  end
440
444
 
@@ -3,12 +3,12 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class AuthorizationCodeRequest < BaseRequest
6
- validate :params, error: :invalid_request
7
- validate :client, error: :invalid_client
8
- validate :grant, error: :invalid_grant
6
+ validate :params, error: Errors::InvalidRequest
7
+ validate :client, error: Errors::InvalidClient
8
+ validate :grant, error: Errors::InvalidGrant
9
9
  # @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
10
- validate :redirect_uri, error: :invalid_grant
11
- validate :code_verifier, error: :invalid_grant
10
+ validate :redirect_uri, error: Errors::InvalidGrant
11
+ validate :code_verifier, error: Errors::InvalidGrant
12
12
 
13
13
  attr_reader :grant, :client, :redirect_uri, :access_token, :code_verifier,
14
14
  :invalid_request_reason, :missing_param
@@ -32,7 +32,7 @@ module Doorkeeper
32
32
  grant.revoke
33
33
 
34
34
  find_or_create_access_token(
35
- grant.application,
35
+ client,
36
36
  resource_owner,
37
37
  grant.scopes,
38
38
  custom_token_attributes_with_data,
@@ -15,7 +15,7 @@ module Doorkeeper
15
15
  @response = TokenResponse.new(access_token)
16
16
  after_successful_response
17
17
  @response
18
- elsif error == :invalid_request
18
+ elsif error == Errors::InvalidRequest
19
19
  @response = InvalidRequestResponse.from_request(self)
20
20
  else
21
21
  @response = ErrorResponse.from_request(self)
@@ -11,10 +11,10 @@ module Doorkeeper
11
11
  @validator = validator
12
12
  end
13
13
 
14
- def create(client, scopes, creator = Creator.new)
14
+ def create(client, scopes, attributes = {}, creator = Creator.new)
15
15
  if validator.valid?
16
- @token = create_token(client, scopes, creator)
17
- @error = :server_error unless @token
16
+ @token = create_token(client, scopes, attributes, creator)
17
+ @error = Errors::ServerError unless @token
18
18
  else
19
19
  @token = false
20
20
  @error = validator.error
@@ -25,7 +25,7 @@ module Doorkeeper
25
25
 
26
26
  private
27
27
 
28
- def create_token(client, scopes, creator)
28
+ def create_token(client, scopes, attributes, creator)
29
29
  context = Authorization::Token.build_context(
30
30
  client,
31
31
  Doorkeeper::OAuth::CLIENT_CREDENTIALS,
@@ -39,6 +39,7 @@ module Doorkeeper
39
39
  scopes,
40
40
  use_refresh_token: false,
41
41
  expires_in: ttl,
42
+ **attributes
42
43
  )
43
44
  end
44
45
  end
@@ -7,9 +7,9 @@ module Doorkeeper
7
7
  include Validations
8
8
  include OAuth::Helpers
9
9
 
10
- validate :client, error: :invalid_client
11
- validate :client_supports_grant_flow, error: :unauthorized_client
12
- validate :scopes, error: :invalid_scope
10
+ validate :client, error: Errors::InvalidClient
11
+ validate :client_supports_grant_flow, error: Errors::UnauthorizedClient
12
+ validate :scopes, error: Errors::InvalidScope
13
13
 
14
14
  def initialize(server, request)
15
15
  @server = server
@@ -3,7 +3,7 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class ClientCredentialsRequest < BaseRequest
6
- attr_reader :client, :original_scopes, :response
6
+ attr_reader :client, :original_scopes, :parameters, :response
7
7
 
8
8
  alias error_response response
9
9
 
@@ -14,6 +14,7 @@ module Doorkeeper
14
14
  @server = server
15
15
  @response = nil
16
16
  @original_scopes = parameters[:scope]
17
+ @parameters = parameters.except(:scope)
17
18
  end
18
19
 
19
20
  def access_token
@@ -30,7 +31,14 @@ module Doorkeeper
30
31
  private
31
32
 
32
33
  def valid?
33
- issuer.create(client, scopes)
34
+ issuer.create(client, scopes, custom_token_attributes_with_data)
35
+ end
36
+
37
+ def custom_token_attributes_with_data
38
+ parameters
39
+ .with_indifferent_access
40
+ .slice(*Doorkeeper.config.custom_access_token_attributes)
41
+ .symbolize_keys
34
42
  end
35
43
  end
36
44
  end
@@ -17,7 +17,7 @@ module Doorkeeper
17
17
  end
18
18
 
19
19
  def deny
20
- pre_auth.error = :access_denied
20
+ pre_auth.error = Errors::AccessDenied
21
21
  pre_auth.error_response
22
22
  end
23
23
  end
@@ -10,7 +10,8 @@ module Doorkeeper
10
10
  def self.from_request(request, attributes = {})
11
11
  new(
12
12
  attributes.merge(
13
- name: request.error,
13
+ name: request.error&.name_for_response,
14
+ exception_class: request.error,
14
15
  state: request.try(:state),
15
16
  redirect_uri: request.try(:redirect_uri),
16
17
  ),
@@ -21,6 +22,7 @@ module Doorkeeper
21
22
 
22
23
  def initialize(attributes = {})
23
24
  @error = OAuth::Error.new(*attributes.values_at(:name, :state))
25
+ @exception_class = attributes[:exception_class]
24
26
  @redirect_uri = attributes[:redirect_uri]
25
27
  @response_on_fragment = attributes[:response_on_fragment]
26
28
  end
@@ -72,6 +74,7 @@ module Doorkeeper
72
74
  end
73
75
 
74
76
  def exception_class
77
+ return @exception_class if @exception_class
75
78
  raise NotImplementedError, "error response must define #exception_class"
76
79
  end
77
80
 
@@ -40,7 +40,7 @@ module Doorkeeper
40
40
 
41
41
  def self.loopback_uri?(uri)
42
42
  IPAddr.new(uri.host).loopback?
43
- rescue IPAddr::Error
43
+ rescue IPAddr::Error, IPAddr::InvalidAddressError
44
44
  false
45
45
  end
46
46
 
@@ -35,6 +35,10 @@ module Doorkeeper
35
35
  )
36
36
  end
37
37
 
38
+ def exception_class
39
+ Doorkeeper::Errors::InvalidRequest
40
+ end
41
+
38
42
  def redirectable?
39
43
  super && @missing_param != :client_id
40
44
  end
@@ -5,10 +5,10 @@ module Doorkeeper
5
5
  class PasswordAccessTokenRequest < BaseRequest
6
6
  include OAuth::Helpers
7
7
 
8
- validate :client, error: :invalid_client
9
- validate :client_supports_grant_flow, error: :unauthorized_client
10
- validate :resource_owner, error: :invalid_grant
11
- validate :scopes, error: :invalid_scope
8
+ validate :client, error: Errors::InvalidClient
9
+ validate :client_supports_grant_flow, error: Errors::UnauthorizedClient
10
+ validate :resource_owner, error: Errors::InvalidGrant
11
+ validate :scopes, error: Errors::InvalidScope
12
12
 
13
13
  attr_reader :client, :credentials, :resource_owner, :parameters, :access_token
14
14
 
@@ -5,16 +5,16 @@ module Doorkeeper
5
5
  class PreAuthorization
6
6
  include Validations
7
7
 
8
- validate :client_id, error: :invalid_request
9
- validate :client, error: :invalid_client
10
- validate :client_supports_grant_flow, error: :unauthorized_client
11
- validate :resource_owner_authorize_for_client, error: :invalid_client
12
- validate :redirect_uri, error: :invalid_redirect_uri
13
- validate :params, error: :invalid_request
14
- validate :response_type, error: :unsupported_response_type
15
- validate :response_mode, error: :unsupported_response_mode
16
- validate :scopes, error: :invalid_scope
17
- validate :code_challenge_method, error: :invalid_code_challenge_method
8
+ validate :client_id, error: Errors::InvalidRequest
9
+ validate :client, error: Errors::InvalidClient
10
+ validate :client_supports_grant_flow, error: Errors::UnauthorizedClient
11
+ validate :resource_owner_authorize_for_client, error: Errors::InvalidClient
12
+ validate :redirect_uri, error: Errors::InvalidRedirectUri
13
+ validate :params, error: Errors::InvalidRequest
14
+ validate :response_type, error: Errors::UnsupportedResponseType
15
+ validate :response_mode, error: Errors::UnsupportedResponseMode
16
+ validate :scopes, error: Errors::InvalidScope
17
+ validate :code_challenge_method, error: Errors::InvalidCodeChallengeMethod
18
18
 
19
19
  attr_reader :client, :code_challenge, :code_challenge_method, :missing_param,
20
20
  :redirect_uri, :resource_owner, :response_type, :state,
@@ -47,7 +47,7 @@ module Doorkeeper
47
47
  end
48
48
 
49
49
  def error_response
50
- if error == :invalid_request
50
+ if error == Errors::InvalidRequest
51
51
  OAuth::InvalidRequestResponse.from_request(
52
52
  self,
53
53
  response_on_fragment: response_on_fragment?,
@@ -5,11 +5,11 @@ module Doorkeeper
5
5
  class RefreshTokenRequest < BaseRequest
6
6
  include OAuth::Helpers
7
7
 
8
- validate :token_presence, error: :invalid_request
9
- validate :token, error: :invalid_grant
10
- validate :client, error: :invalid_client
11
- validate :client_match, error: :invalid_grant
12
- validate :scope, error: :invalid_scope
8
+ validate :token_presence, error: Errors::InvalidRequest
9
+ validate :token, error: Errors::InvalidGrant
10
+ validate :client, error: Errors::InvalidClient
11
+ validate :client_match, error: Errors::InvalidGrant
12
+ validate :scope, error: Errors::InvalidScope
13
13
 
14
14
  attr_reader :access_token, :client, :credentials, :refresh_token
15
15
  attr_reader :missing_param
@@ -6,6 +6,8 @@ module Doorkeeper
6
6
  #
7
7
  # @see https://datatracker.ietf.org/doc/html/rfc7662
8
8
  class TokenIntrospection
9
+ attr_reader :error
10
+
9
11
  def initialize(server, token)
10
12
  @server = server
11
13
  @token = token
@@ -20,12 +22,12 @@ module Doorkeeper
20
22
  def error_response
21
23
  return if @error.blank?
22
24
 
23
- if @error == :invalid_token
25
+ if @error == Errors::InvalidToken
24
26
  OAuth::InvalidTokenResponse.from_access_token(authorized_token)
25
- elsif @error == :invalid_request
27
+ elsif @error == Errors::InvalidRequest
26
28
  OAuth::InvalidRequestResponse.from_request(self)
27
29
  else
28
- OAuth::ErrorResponse.new(name: @error)
30
+ OAuth::ErrorResponse.from_request(self)
29
31
  end
30
32
  end
31
33
 
@@ -36,7 +38,7 @@ module Doorkeeper
36
38
  private
37
39
 
38
40
  attr_reader :server, :token
39
- attr_reader :error, :invalid_request_reason
41
+ attr_reader :invalid_request_reason
40
42
 
41
43
  # If the protected resource uses OAuth 2.0 client credentials to
42
44
  # authenticate to the introspection endpoint and its credentials are
@@ -58,7 +60,7 @@ module Doorkeeper
58
60
  def authorize!
59
61
  # Requested client authorization
60
62
  if server.credentials
61
- @error = :invalid_client unless authorized_client
63
+ @error = Errors::InvalidClient unless authorized_client
62
64
  elsif authorized_token
63
65
  # Requested bearer token authorization
64
66
  #
@@ -69,9 +71,9 @@ module Doorkeeper
69
71
  # HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
70
72
  # Usage [RFC6750].
71
73
  #
72
- @error = :invalid_token unless valid_authorized_token?
74
+ @error = Errors::InvalidToken unless valid_authorized_token?
73
75
  else
74
- @error = :invalid_request
76
+ @error = Errors::InvalidRequest
75
77
  @invalid_request_reason = :request_not_authorized
76
78
  end
77
79
  end
@@ -17,7 +17,7 @@ module Doorkeeper
17
17
  end
18
18
 
19
19
  def deny
20
- pre_auth.error = :access_denied
20
+ pre_auth.error = Errors::AccessDenied
21
21
  pre_auth.error_response
22
22
  end
23
23
  end
@@ -22,7 +22,7 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
22
22
 
23
23
  validates :name, :secret, :uid, presence: true
24
24
  validates :uid, uniqueness: { case_sensitive: true }
25
- validates :redirect_uri, "doorkeeper/redirect_uri": true
25
+ validates_with Doorkeeper::RedirectUriValidator, attributes: [:redirect_uri]
26
26
  validates :confidential, inclusion: { in: [true, false] }
27
27
 
28
28
  validate :scopes_match_configured, if: :enforce_scopes?
@@ -5,7 +5,7 @@ module Doorkeeper
5
5
  # Semantic versioning
6
6
  MAJOR = 5
7
7
  MINOR = 6
8
- TINY = 6
8
+ TINY = 8
9
9
  PRE = nil
10
10
 
11
11
  # Full version number
@@ -312,6 +312,12 @@ Doorkeeper.configure do
312
312
  # Doorkeeper::Errors::TokenRevoked, Doorkeeper::Errors::TokenUnknown
313
313
  #
314
314
  # handle_auth_errors :raise
315
+ #
316
+ # If you want to redirect back to the client application in accordance with
317
+ # https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1, you can set
318
+ # +handle_auth_errors+ to :redirect
319
+ #
320
+ # handle_auth_errors :redirect
315
321
 
316
322
  # Customize token introspection response.
317
323
  # Allows to add your own fields to default one that are required by the OAuth spec
@@ -385,7 +391,7 @@ Doorkeeper.configure do
385
391
  # true in case resource owner authorized for the specific application or false in other
386
392
  # cases.
387
393
  #
388
- # Be default all Resource Owners are authorized to any Client (application).
394
+ # By default all Resource Owners are authorized to any Client (application).
389
395
  #
390
396
  # authorize_resource_owner_for_client do |client, resource_owner|
391
397
  # resource_owner.admin? || client.owners_allowlist.include?(resource_owner)
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.6
4
+ version: 5.6.8
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-03-29 00:00:00.000000000 Z
14
+ date: 2023-12-01 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: railties