doorkeeper 5.3.0 → 5.4.0.rc1

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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +0 -14
  3. data/CHANGELOG.md +44 -1
  4. data/Dangerfile +7 -7
  5. data/Dockerfile +2 -2
  6. data/Gemfile +9 -9
  7. data/README.md +6 -4
  8. data/app/controllers/doorkeeper/applications_controller.rb +4 -4
  9. data/app/controllers/doorkeeper/authorizations_controller.rb +31 -12
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  11. data/app/controllers/doorkeeper/tokens_controller.rb +57 -20
  12. data/app/views/doorkeeper/applications/show.html.erb +19 -2
  13. data/bin/console +14 -0
  14. data/config/locales/en.yml +3 -1
  15. data/doorkeeper.gemspec +1 -1
  16. data/gemfiles/rails_5_0.gemfile +8 -7
  17. data/gemfiles/rails_5_1.gemfile +8 -7
  18. data/gemfiles/rails_5_2.gemfile +8 -7
  19. data/gemfiles/rails_6_0.gemfile +8 -7
  20. data/gemfiles/rails_master.gemfile +8 -7
  21. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  22. data/lib/doorkeeper/config/option.rb +28 -14
  23. data/lib/doorkeeper/config.rb +41 -17
  24. data/lib/doorkeeper/grape/helpers.rb +1 -1
  25. data/lib/doorkeeper/models/access_grant_mixin.rb +9 -11
  26. data/lib/doorkeeper/models/access_token_mixin.rb +102 -42
  27. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  28. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  29. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  30. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  31. data/lib/doorkeeper/oauth/authorization/code.rb +14 -5
  32. data/lib/doorkeeper/oauth/authorization/context.rb +2 -2
  33. data/lib/doorkeeper/oauth/authorization/token.rb +7 -11
  34. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  35. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -8
  36. data/lib/doorkeeper/oauth/base_request.rb +11 -19
  37. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  38. data/lib/doorkeeper/oauth/client.rb +1 -1
  39. data/lib/doorkeeper/oauth/client_credentials/creator.rb +25 -7
  40. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  41. data/lib/doorkeeper/oauth/client_credentials/validator.rb +1 -1
  42. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  43. data/lib/doorkeeper/oauth/code_request.rb +1 -1
  44. data/lib/doorkeeper/oauth/code_response.rb +6 -2
  45. data/lib/doorkeeper/oauth/error_response.rb +2 -4
  46. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -5
  47. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  48. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  49. data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -5
  50. data/lib/doorkeeper/oauth/pre_authorization.rb +32 -27
  51. data/lib/doorkeeper/oauth/refresh_token_request.rb +18 -22
  52. data/lib/doorkeeper/oauth/token.rb +1 -1
  53. data/lib/doorkeeper/oauth/token_introspection.rb +3 -3
  54. data/lib/doorkeeper/oauth/token_request.rb +2 -2
  55. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  56. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +7 -2
  57. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +6 -2
  58. data/lib/doorkeeper/orm/active_record/mixins/application.rb +6 -2
  59. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  60. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  61. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  62. data/lib/doorkeeper/rails/routes.rb +13 -17
  63. data/lib/doorkeeper/request/strategy.rb +2 -2
  64. data/lib/doorkeeper/server.rb +3 -3
  65. data/lib/doorkeeper/version.rb +2 -2
  66. data/lib/doorkeeper.rb +106 -79
  67. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  68. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  69. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +2 -0
  70. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  71. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  72. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  73. data/lib/generators/doorkeeper/templates/initializer.rb +47 -3
  74. data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -0
  75. data/spec/controllers/applications_controller_spec.rb +2 -2
  76. data/spec/controllers/authorizations_controller_spec.rb +165 -30
  77. data/spec/controllers/tokens_controller_spec.rb +6 -5
  78. data/spec/dummy/app/helpers/application_helper.rb +1 -1
  79. data/spec/dummy/app/models/user.rb +5 -1
  80. data/spec/dummy/config/application.rb +6 -4
  81. data/spec/dummy/config/boot.rb +4 -4
  82. data/spec/dummy/config/environment.rb +1 -1
  83. data/spec/dummy/config/routes.rb +4 -4
  84. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +2 -2
  85. data/spec/dummy/db/schema.rb +3 -1
  86. data/spec/factories.rb +1 -1
  87. data/spec/generators/enable_polymorphic_resource_owner_generator_spec.rb +47 -0
  88. data/spec/lib/config_spec.rb +30 -11
  89. data/spec/lib/models/revocable_spec.rb +2 -3
  90. data/spec/lib/models/scopes_spec.rb +8 -0
  91. data/spec/lib/oauth/authorization_code_request_spec.rb +25 -15
  92. data/spec/lib/oauth/base_request_spec.rb +6 -20
  93. data/spec/lib/oauth/client_credentials/creator_spec.rb +90 -89
  94. data/spec/lib/oauth/client_credentials/issuer_spec.rb +84 -86
  95. data/spec/lib/oauth/client_credentials/validation_spec.rb +38 -40
  96. data/spec/lib/oauth/client_credentials_request_spec.rb +5 -4
  97. data/spec/lib/oauth/code_request_spec.rb +1 -1
  98. data/spec/lib/oauth/code_response_spec.rb +5 -1
  99. data/spec/lib/oauth/error_response_spec.rb +1 -1
  100. data/spec/lib/oauth/password_access_token_request_spec.rb +24 -13
  101. data/spec/lib/oauth/pre_authorization_spec.rb +13 -18
  102. data/spec/lib/oauth/refresh_token_request_spec.rb +19 -30
  103. data/spec/lib/oauth/token_request_spec.rb +14 -7
  104. data/spec/lib/option_spec.rb +51 -0
  105. data/spec/lib/stale_records_cleaner_spec.rb +18 -5
  106. data/spec/models/doorkeeper/access_grant_spec.rb +18 -4
  107. data/spec/models/doorkeeper/access_token_spec.rb +507 -479
  108. data/spec/models/doorkeeper/application_spec.rb +338 -300
  109. data/spec/requests/endpoints/token_spec.rb +5 -1
  110. data/spec/requests/flows/authorization_code_errors_spec.rb +4 -1
  111. data/spec/requests/flows/authorization_code_spec.rb +6 -1
  112. data/spec/requests/flows/client_credentials_spec.rb +41 -0
  113. data/spec/requests/flows/refresh_token_spec.rb +16 -8
  114. data/spec/requests/flows/revoke_token_spec.rb +143 -104
  115. data/spec/support/helpers/access_token_request_helper.rb +1 -0
  116. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  117. data/spec/support/helpers/config_helper.rb +1 -1
  118. data/spec/support/shared/controllers_shared_context.rb +2 -2
  119. data/spec/support/shared/models_shared_examples.rb +6 -4
  120. metadata +15 -4
@@ -7,9 +7,9 @@ module Doorkeeper
7
7
  attr_reader :client, :grant_type, :scopes
8
8
 
9
9
  def initialize(client, grant_type, scopes)
10
- @client = client
10
+ @client = client
11
11
  @grant_type = grant_type
12
- @scopes = scopes
12
+ @scopes = scopes
13
13
  end
14
14
  end
15
15
  end
@@ -4,7 +4,7 @@ module Doorkeeper
4
4
  module OAuth
5
5
  module Authorization
6
6
  class Token
7
- attr_accessor :pre_auth, :resource_owner, :token
7
+ attr_reader :pre_auth, :resource_owner, :token
8
8
 
9
9
  class << self
10
10
  def build_context(pre_auth_or_oauth_client, grant_type, scopes)
@@ -57,12 +57,12 @@ module Doorkeeper
57
57
  pre_auth.scopes,
58
58
  )
59
59
 
60
- @token = configuration.access_token_model.find_or_create_for(
61
- pre_auth.client,
62
- resource_owner.id,
63
- pre_auth.scopes,
64
- self.class.access_token_expires_in(configuration, context),
65
- false,
60
+ @token = Doorkeeper.config.access_token_model.find_or_create_for(
61
+ application: pre_auth.client,
62
+ resource_owner: resource_owner,
63
+ scopes: pre_auth.scopes,
64
+ expires_in: self.class.access_token_expires_in(Doorkeeper.config, context),
65
+ use_refresh_token: false,
66
66
  )
67
67
  end
68
68
 
@@ -76,10 +76,6 @@ module Doorkeeper
76
76
 
77
77
  private
78
78
 
79
- def configuration
80
- Doorkeeper.config
81
- end
82
-
83
79
  def controller
84
80
  @controller ||= begin
85
81
  mapping = Doorkeeper::Rails::Routes.mapping[:token_info] || {}
@@ -8,9 +8,9 @@ module Doorkeeper
8
8
  class URIBuilder
9
9
  class << self
10
10
  def uri_with_query(url, parameters = {})
11
- uri = URI.parse(url)
11
+ uri = URI.parse(url)
12
12
  original_query = Rack::Utils.parse_query(uri.query)
13
- uri.query = build_query(original_query.merge(parameters))
13
+ uri.query = build_query(original_query.merge(parameters))
14
14
  uri.to_s
15
15
  end
16
16
 
@@ -23,8 +23,8 @@ module Doorkeeper
23
23
  private
24
24
 
25
25
  def build_query(parameters = {})
26
- parameters = parameters.reject { |_, v| v.blank? }
27
- Rack::Utils.build_query parameters
26
+ parameters = parameters.reject { |_, value| value.blank? }
27
+ Rack::Utils.build_query(parameters)
28
28
  end
29
29
  end
30
30
  end
@@ -11,9 +11,8 @@ module Doorkeeper
11
11
  validate :redirect_uri, error: :invalid_grant
12
12
  validate :code_verifier, error: :invalid_grant
13
13
 
14
- attr_accessor :server, :grant, :client, :redirect_uri, :access_token,
15
- :code_verifier
16
- attr_reader :invalid_request_reason, :missing_param
14
+ attr_reader :grant, :client, :redirect_uri, :access_token, :code_verifier,
15
+ :invalid_request_reason, :missing_param
17
16
 
18
17
  def initialize(server, grant, client, parameters = {})
19
18
  @server = server
@@ -33,19 +32,30 @@ module Doorkeeper
33
32
 
34
33
  grant.revoke
35
34
 
35
+ resource_owner = if Doorkeeper.config.polymorphic_resource_owner?
36
+ grant.resource_owner
37
+ else
38
+ grant.resource_owner_id
39
+ end
40
+
36
41
  find_or_create_access_token(
37
42
  grant.application,
38
- grant.resource_owner_id,
43
+ resource_owner,
39
44
  grant.scopes,
40
45
  server,
41
46
  )
42
47
  end
48
+
43
49
  super
44
50
  end
45
51
 
52
+ def pkce_supported?
53
+ Doorkeeper.config.access_grant_model.pkce_supported?
54
+ end
55
+
46
56
  def validate_pkce_support
47
57
  @invalid_request_reason = :not_support_pkce if grant &&
48
- !grant.pkce_supported? &&
58
+ !pkce_supported? &&
49
59
  code_verifier.present?
50
60
 
51
61
  @invalid_request_reason.nil?
@@ -78,11 +88,11 @@ module Doorkeeper
78
88
  )
79
89
  end
80
90
 
81
- # if either side (server or client) request pkce, check the verifier
82
- # against the DB - if pkce is supported
91
+ # if either side (server or client) request PKCE, check the verifier
92
+ # against the DB - if PKCE is supported
83
93
  def validate_code_verifier
84
94
  return true unless grant.uses_pkce? || code_verifier
85
- return false unless grant.pkce_supported?
95
+ return false unless pkce_supported?
86
96
 
87
97
  if grant.code_challenge_method == "S256"
88
98
  grant.code_challenge == generate_code_challenge(code_verifier)
@@ -5,11 +5,11 @@ module Doorkeeper
5
5
  class BaseRequest
6
6
  include Validations
7
7
 
8
- attr_reader :grant_type
8
+ attr_reader :grant_type, :server
9
9
 
10
- def authorize
11
- validate
10
+ delegate :default_scopes, to: :server
12
11
 
12
+ def authorize
13
13
  if valid?
14
14
  before_successful_response
15
15
  @response = TokenResponse.new(access_token)
@@ -26,22 +26,14 @@ module Doorkeeper
26
26
  @scopes ||= build_scopes
27
27
  end
28
28
 
29
- def default_scopes
30
- server.default_scopes
31
- end
32
-
33
- def valid?
34
- error.nil?
35
- end
36
-
37
- def find_or_create_access_token(client, resource_owner_id, scopes, server)
29
+ def find_or_create_access_token(client, resource_owner, scopes, server)
38
30
  context = Authorization::Token.build_context(client, grant_type, scopes)
39
31
  @access_token = server_config.access_token_model.find_or_create_for(
40
- client,
41
- resource_owner_id,
42
- scopes,
43
- Authorization::Token.access_token_expires_in(server, context),
44
- Authorization::Token.refresh_token_enabled?(server, context),
32
+ application: client,
33
+ resource_owner: resource_owner,
34
+ scopes: scopes,
35
+ expires_in: Authorization::Token.access_token_expires_in(server, context),
36
+ use_refresh_token: Authorization::Token.refresh_token_enabled?(server, context),
45
37
  )
46
38
  end
47
39
 
@@ -63,10 +55,10 @@ module Doorkeeper
63
55
  if @original_scopes.present?
64
56
  OAuth::Scopes.from_string(@original_scopes)
65
57
  else
66
- client_scopes = @client.try(:scopes)
58
+ client_scopes = @client&.scopes
67
59
  return default_scopes if client_scopes.blank?
68
60
 
69
- default_scopes & @client.scopes
61
+ default_scopes & client_scopes
70
62
  end
71
63
  end
72
64
  end
@@ -9,7 +9,7 @@ module Doorkeeper
9
9
  credentials_methods.inject(nil) do |_, method|
10
10
  method = self.method(method) if method.is_a?(Symbol)
11
11
  credentials = Credentials.new(*method.call(request))
12
- break credentials unless credentials.blank?
12
+ break credentials if credentials.present?
13
13
  end
14
14
  end
15
15
 
@@ -27,9 +27,7 @@ module Doorkeeper
27
27
 
28
28
  # Public clients may have their secret blank, but "credentials" are
29
29
  # still present
30
- def blank?
31
- uid.blank?
32
- end
30
+ delegate :blank?, to: :uid
33
31
  end
34
32
  end
35
33
  end
@@ -3,7 +3,7 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class Client
6
- attr_accessor :application
6
+ attr_reader :application
7
7
 
8
8
  delegate :id, :name, :uid, :redirect_uri, :scopes, to: :@application
9
9
 
@@ -2,24 +2,42 @@
2
2
 
3
3
  module Doorkeeper
4
4
  module OAuth
5
- class ClientCredentialsRequest < BaseRequest
5
+ module ClientCredentials
6
6
  class Creator
7
7
  def call(client, scopes, attributes = {})
8
+ existing_token = nil
9
+
8
10
  if lookup_existing_token?
9
11
  existing_token = find_existing_token_for(client, scopes)
10
12
  return existing_token if server_config.reuse_access_token && existing_token&.reusable?
11
-
12
- existing_token&.revoke if server_config.revoke_previous_client_credentials_token
13
13
  end
14
14
 
15
- server_config.access_token_model.find_or_create_for(
16
- client, nil, scopes, attributes[:expires_in],
17
- attributes[:use_refresh_token],
18
- )
15
+ with_revocation(existing_token: existing_token) do
16
+ server_config.access_token_model.find_or_create_for(
17
+ application: client,
18
+ resource_owner: nil,
19
+ scopes: scopes,
20
+ **attributes,
21
+ )
22
+ end
19
23
  end
20
24
 
21
25
  private
22
26
 
27
+ def with_revocation(existing_token:)
28
+ if existing_token && server_config.revoke_previous_client_credentials_token
29
+ existing_token.with_lock do
30
+ raise Errors::DoorkeeperError, :invalid_token_reuse if existing_token.revoked?
31
+
32
+ existing_token.revoke
33
+
34
+ yield
35
+ end
36
+ else
37
+ yield
38
+ end
39
+ end
40
+
23
41
  def lookup_existing_token?
24
42
  server_config.reuse_access_token || server_config.revoke_previous_client_credentials_token
25
43
  end
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Doorkeeper
4
4
  module OAuth
5
- class ClientCredentialsRequest < BaseRequest
5
+ module ClientCredentials
6
6
  class Issuer
7
- attr_accessor :token, :validator, :error
7
+ attr_reader :token, :validator, :error
8
8
 
9
9
  def initialize(server, validator)
10
10
  @server = server
@@ -19,6 +19,7 @@ module Doorkeeper
19
19
  @token = false
20
20
  @error = validator.error
21
21
  end
22
+
22
23
  @token
23
24
  end
24
25
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Doorkeeper
4
4
  module OAuth
5
- class ClientCredentialsRequest < BaseRequest
5
+ module ClientCredentials
6
6
  class Validator
7
7
  include Validations
8
8
  include OAuth::Helpers
@@ -3,18 +3,12 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class ClientCredentialsRequest < BaseRequest
6
- attr_accessor :server, :client, :original_scopes
7
- attr_reader :response
8
- attr_writer :issuer
6
+ attr_reader :client, :original_scopes, :response
9
7
 
10
8
  alias error_response response
11
9
 
12
10
  delegate :error, to: :issuer
13
11
 
14
- def issuer
15
- @issuer ||= Issuer.new(server, Validator.new(server, self))
16
- end
17
-
18
12
  def initialize(server, client, parameters = {})
19
13
  @client = client
20
14
  @server = server
@@ -26,6 +20,13 @@ module Doorkeeper
26
20
  issuer.token
27
21
  end
28
22
 
23
+ def issuer
24
+ @issuer ||= ClientCredentials::Issuer.new(
25
+ server,
26
+ ClientCredentials::Validator.new(server, self),
27
+ )
28
+ end
29
+
29
30
  private
30
31
 
31
32
  def valid?
@@ -3,7 +3,7 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class CodeRequest
6
- attr_accessor :pre_auth, :resource_owner
6
+ attr_reader :pre_auth, :resource_owner
7
7
 
8
8
  def initialize(pre_auth, resource_owner)
9
9
  @pre_auth = pre_auth
@@ -5,7 +5,7 @@ module Doorkeeper
5
5
  class CodeResponse < BaseResponse
6
6
  include OAuth::Helpers
7
7
 
8
- attr_accessor :pre_auth, :auth, :response_on_fragment
8
+ attr_reader :pre_auth, :auth, :response_on_fragment
9
9
 
10
10
  def initialize(pre_auth, auth, options = {})
11
11
  @pre_auth = pre_auth
@@ -17,8 +17,12 @@ module Doorkeeper
17
17
  true
18
18
  end
19
19
 
20
+ def issued_token
21
+ auth.token
22
+ end
23
+
20
24
  def redirect_uri
21
- if URIChecker.oob_uri? pre_auth.redirect_uri
25
+ if URIChecker.oob_uri?(pre_auth.redirect_uri)
22
26
  auth.oob_redirect
23
27
  elsif response_on_fragment
24
28
  Authorization::URIBuilder.uri_with_fragment(
@@ -67,10 +67,8 @@ module Doorkeeper
67
67
 
68
68
  protected
69
69
 
70
- delegate :realm, to: :configuration
71
-
72
- def configuration
73
- Doorkeeper.config
70
+ def realm
71
+ Doorkeeper.config.realm
74
72
  end
75
73
 
76
74
  def exception_class
@@ -27,11 +27,7 @@ module Doorkeeper
27
27
  private
28
28
 
29
29
  def valid_scopes(server_scopes, app_scopes)
30
- if app_scopes.present?
31
- app_scopes
32
- else
33
- server_scopes
34
- end
30
+ app_scopes.presence || server_scopes
35
31
  end
36
32
 
37
33
  def permitted_to_grant_type?
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ module Hooks
6
+ class Context
7
+ attr_reader :auth, :pre_auth
8
+
9
+ def initialize(**attributes)
10
+ attributes.each do |name, value|
11
+ instance_variable_set(:"@#{name}", value) if respond_to?(name)
12
+ end
13
+ end
14
+
15
+ def issued_token
16
+ auth&.issued_token
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -6,9 +6,9 @@ module Doorkeeper
6
6
  attr_reader :reason
7
7
 
8
8
  def self.from_access_token(access_token, attributes = {})
9
- reason = if access_token.try(:revoked?)
9
+ reason = if access_token&.revoked?
10
10
  :revoked
11
- elsif access_token.try(:expired?)
11
+ elsif access_token&.expired?
12
12
  :expired
13
13
  else
14
14
  :unknown
@@ -10,8 +10,7 @@ module Doorkeeper
10
10
  validate :resource_owner, error: :invalid_grant
11
11
  validate :scopes, error: :invalid_scope
12
12
 
13
- attr_accessor :server, :client, :resource_owner, :parameters,
14
- :access_token
13
+ attr_reader :client, :resource_owner, :parameters, :access_token
15
14
 
16
15
  def initialize(server, client, resource_owner, parameters = {})
17
16
  @server = server
@@ -25,18 +24,17 @@ module Doorkeeper
25
24
  private
26
25
 
27
26
  def before_successful_response
28
- find_or_create_access_token(client, resource_owner.id, scopes, server)
27
+ find_or_create_access_token(client, resource_owner, scopes, server)
29
28
  super
30
29
  end
31
30
 
32
31
  def validate_scopes
33
- client_scopes = client.try(:scopes)
34
32
  return true if scopes.blank?
35
33
 
36
34
  ScopeChecker.valid?(
37
35
  scope_str: scopes.to_s,
38
36
  server_scopes: server.scopes,
39
- app_scopes: client_scopes,
37
+ app_scopes: client.try(:scopes),
40
38
  grant_type: grant_type,
41
39
  )
42
40
  end
@@ -5,39 +5,37 @@ 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 :redirect_uri, error: :invalid_redirect_uri
11
- validate :params, error: :invalid_request
12
- validate :response_type, error: :unsupported_response_type
13
- validate :scopes, error: :invalid_scope
8
+ validate :client_id, error: :invalid_request
9
+ validate :client, error: :invalid_client
10
+ validate :resource_owner_authorize_for_client, error: :invalid_client
11
+ validate :redirect_uri, error: :invalid_redirect_uri
12
+ validate :params, error: :invalid_request
13
+ validate :response_type, error: :unsupported_response_type
14
+ validate :scopes, error: :invalid_scope
14
15
  validate :code_challenge_method, error: :invalid_code_challenge_method
15
16
  validate :client_supports_grant_flow, error: :unauthorized_client
16
17
 
17
18
  attr_reader :server, :client_id, :client, :redirect_uri, :response_type, :state,
18
- :code_challenge, :code_challenge_method, :missing_param
19
+ :code_challenge, :code_challenge_method, :missing_param, :resource_owner
19
20
 
20
- def initialize(server, attrs = {})
21
+ def initialize(server, parameters = {}, resource_owner = nil)
21
22
  @server = server
22
- @client_id = attrs[:client_id]
23
- @response_type = attrs[:response_type]
24
- @redirect_uri = attrs[:redirect_uri]
25
- @scope = attrs[:scope]
26
- @state = attrs[:state]
27
- @code_challenge = attrs[:code_challenge]
28
- @code_challenge_method = attrs[:code_challenge_method]
23
+ @client_id = parameters[:client_id]
24
+ @response_type = parameters[:response_type]
25
+ @redirect_uri = parameters[:redirect_uri]
26
+ @scope = parameters[:scope]
27
+ @state = parameters[:state]
28
+ @code_challenge = parameters[:code_challenge]
29
+ @code_challenge_method = parameters[:code_challenge_method]
30
+ @resource_owner = resource_owner
29
31
  end
30
32
 
31
33
  def authorizable?
32
34
  valid?
33
35
  end
34
36
 
35
- def validate_client_supports_grant_flow
36
- Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client.application)
37
- end
38
-
39
37
  def scopes
40
- Scopes.from_string scope
38
+ Scopes.from_string(scope)
41
39
  end
42
40
 
43
41
  def scope
@@ -55,9 +53,7 @@ module Doorkeeper
55
53
  end
56
54
  end
57
55
 
58
- def as_json(attributes = {})
59
- return pre_auth_hash.merge(attributes.to_h) if attributes.respond_to?(:to_h)
60
-
56
+ def as_json(_options = nil)
61
57
  pre_auth_hash
62
58
  end
63
59
 
@@ -83,6 +79,10 @@ module Doorkeeper
83
79
  @client.present?
84
80
  end
85
81
 
82
+ def validate_client_supports_grant_flow
83
+ Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client.application)
84
+ end
85
+
86
86
  def validate_redirect_uri
87
87
  return false if redirect_uri.blank?
88
88
 
@@ -115,19 +115,24 @@ module Doorkeeper
115
115
  )
116
116
  end
117
117
 
118
- def grant_type
119
- response_type == "code" ? AUTHORIZATION_CODE : IMPLICIT
120
- end
121
-
122
118
  def validate_code_challenge_method
123
119
  code_challenge.blank? ||
124
120
  (code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
125
121
  end
126
122
 
123
+ def validate_resource_owner_authorize_for_client
124
+ # The `authorize_resource_owner_for_client` config option is used for this validation
125
+ client.application.authorized_for_resource_owner?(@resource_owner)
126
+ end
127
+
127
128
  def response_on_fragment?
128
129
  response_type == "token"
129
130
  end
130
131
 
132
+ def grant_type
133
+ response_type == "code" ? AUTHORIZATION_CODE : IMPLICIT
134
+ end
135
+
131
136
  def pre_auth_hash
132
137
  {
133
138
  client_id: client.uid,
@@ -11,9 +11,8 @@ module Doorkeeper
11
11
  validate :client_match, error: :invalid_grant
12
12
  validate :scope, error: :invalid_scope
13
13
 
14
- attr_accessor :access_token, :client, :credentials, :refresh_token,
15
- :server
16
- attr_reader :missing_param
14
+ attr_reader :access_token, :client, :credentials, :refresh_token
15
+ attr_reader :missing_param
17
16
 
18
17
  def initialize(server, refresh_token, credentials, parameters = {})
19
18
  @server = server
@@ -50,30 +49,27 @@ module Doorkeeper
50
49
  end
51
50
 
52
51
  def create_access_token
53
- @access_token = server_config.access_token_model.create!(access_token_attributes)
54
- end
52
+ attributes = {}
55
53
 
56
- def access_token_attributes
57
- {
58
- application_id: refresh_token.application_id,
59
- resource_owner_id: refresh_token.resource_owner_id,
60
- scopes: scopes.to_s,
61
- expires_in: access_token_expires_in,
62
- use_refresh_token: true,
63
- }.tap do |attributes|
64
- if refresh_token_revoked_on_use?
65
- attributes[:previous_refresh_token] = refresh_token.refresh_token
54
+ resource_owner =
55
+ if Doorkeeper.config.polymorphic_resource_owner?
56
+ refresh_token.resource_owner
57
+ else
58
+ refresh_token.resource_owner_id
66
59
  end
60
+
61
+ if refresh_token_revoked_on_use?
62
+ attributes[:previous_refresh_token] = refresh_token.refresh_token
67
63
  end
68
- end
69
64
 
70
- def access_token_expires_in
71
- context = Authorization::Token.build_context(
72
- client,
73
- Doorkeeper::OAuth::REFRESH_TOKEN,
74
- scopes,
65
+ @access_token = server_config.access_token_model.create_for(
66
+ application: refresh_token.application,
67
+ resource_owner: resource_owner,
68
+ scopes: scopes,
69
+ expires_in: refresh_token.expires_in,
70
+ use_refresh_token: true,
71
+ **attributes,
75
72
  )
76
- Authorization::Token.access_token_expires_in(server, context)
77
73
  end
78
74
 
79
75
  def validate_token_presence
@@ -8,7 +8,7 @@ module Doorkeeper
8
8
  methods.inject(nil) do |_, method|
9
9
  method = self.method(method) if method.is_a?(Symbol)
10
10
  credentials = method.call(request)
11
- break credentials unless credentials.blank?
11
+ break credentials if credentials.present?
12
12
  end
13
13
  end
14
14
 
@@ -6,9 +6,6 @@ module Doorkeeper
6
6
  #
7
7
  # @see https://tools.ietf.org/html/rfc7662
8
8
  class TokenIntrospection
9
- attr_reader :server, :token
10
- attr_reader :error, :invalid_request_reason
11
-
12
9
  def initialize(server, token)
13
10
  @server = server
14
11
  @token = token
@@ -38,6 +35,9 @@ module Doorkeeper
38
35
 
39
36
  private
40
37
 
38
+ attr_reader :server, :token
39
+ attr_reader :error, :invalid_request_reason
40
+
41
41
  # If the protected resource uses OAuth 2.0 client credentials to
42
42
  # authenticate to the introspection endpoint and its credentials are
43
43
  # invalid, the authorization server responds with an HTTP 401