doorkeeper 5.1.0 → 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.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +3 -3
  3. data/CHANGELOG.md +881 -0
  4. data/CONTRIBUTING.md +11 -9
  5. data/Dangerfile +2 -2
  6. data/Dockerfile +29 -0
  7. data/Gemfile +4 -3
  8. data/NEWS.md +1 -814
  9. data/README.md +11 -3
  10. data/RELEASING.md +6 -5
  11. data/app/controllers/doorkeeper/application_controller.rb +2 -2
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  13. data/app/controllers/doorkeeper/applications_controller.rb +1 -0
  14. data/app/controllers/doorkeeper/authorizations_controller.rb +16 -9
  15. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  16. data/app/controllers/doorkeeper/tokens_controller.rb +32 -9
  17. data/app/views/doorkeeper/applications/_form.html.erb +0 -6
  18. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  19. data/config/locales/en.yml +8 -2
  20. data/doorkeeper.gemspec +9 -1
  21. data/gemfiles/rails_5_0.gemfile +3 -2
  22. data/gemfiles/rails_5_1.gemfile +3 -2
  23. data/gemfiles/rails_5_2.gemfile +3 -2
  24. data/gemfiles/rails_6_0.gemfile +4 -3
  25. data/gemfiles/rails_master.gemfile +3 -2
  26. data/lib/doorkeeper/config/option.rb +13 -7
  27. data/lib/doorkeeper/config.rb +157 -42
  28. data/lib/doorkeeper/errors.rb +13 -18
  29. data/lib/doorkeeper/grape/helpers.rb +6 -2
  30. data/lib/doorkeeper/helpers/controller.rb +28 -7
  31. data/lib/doorkeeper/models/access_grant_mixin.rb +7 -6
  32. data/lib/doorkeeper/models/access_token_mixin.rb +99 -20
  33. data/lib/doorkeeper/models/application_mixin.rb +3 -3
  34. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  35. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  36. data/lib/doorkeeper/models/concerns/revocable.rb +0 -27
  37. data/lib/doorkeeper/oauth/authorization/code.rb +12 -14
  38. data/lib/doorkeeper/oauth/authorization/token.rb +10 -7
  39. data/lib/doorkeeper/oauth/authorization_code_request.rb +31 -15
  40. data/lib/doorkeeper/oauth/base_request.rb +10 -4
  41. data/lib/doorkeeper/oauth/client.rb +7 -8
  42. data/lib/doorkeeper/oauth/client_credentials/creator.rb +23 -2
  43. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -7
  44. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +10 -2
  45. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
  46. data/lib/doorkeeper/oauth/code_request.rb +5 -11
  47. data/lib/doorkeeper/oauth/code_response.rb +4 -4
  48. data/lib/doorkeeper/oauth/error.rb +1 -1
  49. data/lib/doorkeeper/oauth/error_response.rb +6 -6
  50. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +7 -5
  51. data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
  52. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -5
  53. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  54. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -2
  55. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  56. data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
  57. data/lib/doorkeeper/oauth/pre_authorization.rb +76 -38
  58. data/lib/doorkeeper/oauth/refresh_token_request.rb +17 -14
  59. data/lib/doorkeeper/oauth/token.rb +2 -2
  60. data/lib/doorkeeper/oauth/token_introspection.rb +26 -16
  61. data/lib/doorkeeper/oauth/token_request.rb +4 -18
  62. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  63. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  64. data/lib/doorkeeper/orm/active_record/application.rb +5 -83
  65. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +53 -0
  66. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +47 -0
  67. data/lib/doorkeeper/orm/active_record/mixins/application.rb +128 -0
  68. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
  69. data/lib/doorkeeper/orm/active_record.rb +21 -6
  70. data/lib/doorkeeper/rails/helpers.rb +4 -4
  71. data/lib/doorkeeper/rails/routes.rb +5 -7
  72. data/lib/doorkeeper/rake/db.rake +3 -3
  73. data/lib/doorkeeper/request/authorization_code.rb +5 -3
  74. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  75. data/lib/doorkeeper/request/password.rb +2 -2
  76. data/lib/doorkeeper/request/refresh_token.rb +3 -3
  77. data/lib/doorkeeper/request.rb +7 -12
  78. data/lib/doorkeeper/server.rb +3 -7
  79. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  80. data/lib/doorkeeper/version.rb +1 -1
  81. data/lib/doorkeeper.rb +6 -3
  82. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  83. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  84. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  85. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  86. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
  87. data/lib/generators/doorkeeper/templates/initializer.rb +149 -33
  88. data/lib/generators/doorkeeper/templates/migration.rb.erb +4 -1
  89. data/spec/controllers/application_metal_controller_spec.rb +1 -1
  90. data/spec/controllers/applications_controller_spec.rb +95 -1
  91. data/spec/controllers/authorizations_controller_spec.rb +156 -75
  92. data/spec/controllers/protected_resources_controller_spec.rb +28 -20
  93. data/spec/controllers/token_info_controller_spec.rb +1 -1
  94. data/spec/controllers/tokens_controller_spec.rb +206 -38
  95. data/spec/dummy/config/application.rb +3 -1
  96. data/spec/dummy/config/initializers/doorkeeper.rb +54 -9
  97. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -3
  98. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +1 -1
  99. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +1 -1
  100. data/spec/generators/install_generator_spec.rb +1 -1
  101. data/spec/generators/previous_refresh_token_generator_spec.rb +2 -2
  102. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  103. data/spec/lib/config_spec.rb +104 -7
  104. data/spec/lib/doorkeeper_spec.rb +1 -1
  105. data/spec/lib/models/revocable_spec.rb +3 -3
  106. data/spec/lib/oauth/authorization_code_request_spec.rb +129 -115
  107. data/spec/lib/oauth/base_request_spec.rb +154 -135
  108. data/spec/lib/oauth/base_response_spec.rb +27 -29
  109. data/spec/lib/oauth/client/credentials_spec.rb +1 -1
  110. data/spec/lib/oauth/client_credentials/creator_spec.rb +43 -3
  111. data/spec/lib/oauth/client_credentials/issuer_spec.rb +12 -12
  112. data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
  113. data/spec/lib/oauth/client_credentials_integration_spec.rb +16 -18
  114. data/spec/lib/oauth/client_credentials_request_spec.rb +78 -80
  115. data/spec/lib/oauth/client_spec.rb +26 -26
  116. data/spec/lib/oauth/code_request_spec.rb +34 -35
  117. data/spec/lib/oauth/code_response_spec.rb +21 -25
  118. data/spec/lib/oauth/error_response_spec.rb +42 -44
  119. data/spec/lib/oauth/error_spec.rb +12 -14
  120. data/spec/lib/oauth/forbidden_token_response_spec.rb +11 -13
  121. data/spec/lib/oauth/helpers/scope_checker_spec.rb +30 -18
  122. data/spec/lib/oauth/helpers/uri_checker_spec.rb +17 -2
  123. data/spec/lib/oauth/invalid_request_response_spec.rb +73 -0
  124. data/spec/lib/oauth/invalid_token_response_spec.rb +32 -34
  125. data/spec/lib/oauth/password_access_token_request_spec.rb +145 -147
  126. data/spec/lib/oauth/pre_authorization_spec.rb +161 -153
  127. data/spec/lib/oauth/refresh_token_request_spec.rb +138 -138
  128. data/spec/lib/oauth/scopes_spec.rb +104 -106
  129. data/spec/lib/oauth/token_request_spec.rb +117 -110
  130. data/spec/lib/oauth/token_response_spec.rb +71 -73
  131. data/spec/lib/oauth/token_spec.rb +121 -123
  132. data/spec/lib/server_spec.rb +0 -12
  133. data/spec/models/doorkeeper/access_grant_spec.rb +21 -4
  134. data/spec/models/doorkeeper/access_token_spec.rb +42 -11
  135. data/spec/models/doorkeeper/application_spec.rb +114 -77
  136. data/spec/requests/applications/applications_request_spec.rb +1 -1
  137. data/spec/requests/endpoints/authorization_spec.rb +26 -8
  138. data/spec/requests/endpoints/token_spec.rb +1 -1
  139. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -0
  140. data/spec/requests/flows/authorization_code_spec.rb +123 -45
  141. data/spec/requests/flows/client_credentials_spec.rb +38 -0
  142. data/spec/requests/flows/implicit_grant_errors_spec.rb +22 -10
  143. data/spec/requests/flows/implicit_grant_spec.rb +9 -8
  144. data/spec/requests/flows/password_spec.rb +67 -10
  145. data/spec/requests/flows/refresh_token_spec.rb +20 -20
  146. data/spec/requests/flows/revoke_token_spec.rb +37 -23
  147. data/spec/spec_helper.rb +1 -4
  148. data/spec/support/doorkeeper_rspec.rb +1 -1
  149. data/spec/support/helpers/request_spec_helper.rb +14 -2
  150. data/spec/support/shared/controllers_shared_context.rb +33 -23
  151. data/spec/validators/redirect_uri_validator_spec.rb +41 -16
  152. metadata +19 -16
  153. data/.coveralls.yml +0 -1
  154. data/.github/ISSUE_TEMPLATE.md +0 -25
  155. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  156. data/.gitignore +0 -20
  157. data/.gitlab-ci.yml +0 -16
  158. data/.hound.yml +0 -3
  159. data/.rspec +0 -1
  160. data/.rubocop.yml +0 -50
  161. data/.travis.yml +0 -35
  162. data/app/validators/redirect_uri_validator.rb +0 -50
  163. data/spec/support/http_method_shim.rb +0 -29
@@ -12,7 +12,7 @@ module Doorkeeper
12
12
  delegate :error, to: :issuer
13
13
 
14
14
  def issuer
15
- @issuer ||= Issuer.new(server, Validation.new(server, self))
15
+ @issuer ||= Issuer.new(server, Validator.new(server, self))
16
16
  end
17
17
 
18
18
  def initialize(server, client, parameters = {})
@@ -3,28 +3,22 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class CodeRequest
6
- attr_accessor :pre_auth, :resource_owner, :client
6
+ attr_accessor :pre_auth, :resource_owner
7
7
 
8
8
  def initialize(pre_auth, resource_owner)
9
9
  @pre_auth = pre_auth
10
- @client = pre_auth.client
11
10
  @resource_owner = resource_owner
12
11
  end
13
12
 
14
13
  def authorize
15
- if pre_auth.authorizable?
16
- auth = Authorization::Code.new(pre_auth, resource_owner)
17
- auth.issue_token
18
- @response = CodeResponse.new pre_auth, auth
19
- else
20
- @response = ErrorResponse.from_request pre_auth
21
- end
14
+ auth = Authorization::Code.new(pre_auth, resource_owner)
15
+ auth.issue_token
16
+ CodeResponse.new(pre_auth, auth)
22
17
  end
23
18
 
24
19
  def deny
25
20
  pre_auth.error = :access_denied
26
- ErrorResponse.from_request pre_auth,
27
- redirect_uri: pre_auth.redirect_uri
21
+ pre_auth.error_response
28
22
  end
29
23
  end
30
24
  end
@@ -18,21 +18,21 @@ module Doorkeeper
18
18
  end
19
19
 
20
20
  def redirect_uri
21
- if URIChecker.native_uri? pre_auth.redirect_uri
22
- auth.native_redirect
21
+ if URIChecker.oob_uri? pre_auth.redirect_uri
22
+ auth.oob_redirect
23
23
  elsif response_on_fragment
24
24
  Authorization::URIBuilder.uri_with_fragment(
25
25
  pre_auth.redirect_uri,
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
@@ -7,7 +7,7 @@ module Doorkeeper
7
7
  I18n.translate(
8
8
  name,
9
9
  scope: %i[doorkeeper errors messages],
10
- default: :server_error
10
+ default: :server_error,
11
11
  )
12
12
  end
13
13
  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
 
@@ -41,14 +41,14 @@ module Doorkeeper
41
41
 
42
42
  def redirectable?
43
43
  name != :invalid_redirect_uri && name != :invalid_client &&
44
- !URIChecker.native_uri?(@redirect_uri)
44
+ !URIChecker.oob_uri?(@redirect_uri)
45
45
  end
46
46
 
47
47
  def redirect_uri
48
48
  if @response_on_fragment
49
- Authorization::URIBuilder.uri_with_fragment @redirect_uri, body
49
+ Authorization::URIBuilder.uri_with_fragment(@redirect_uri, body)
50
50
  else
51
- Authorization::URIBuilder.uri_with_query @redirect_uri, body
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.configuration
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.configuration.scopes_by_grant_type[grant_type.to_sym]
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(scope_str,
47
- server_scopes,
48
- app_scopes,
49
- grant_type).valid?
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
- generator_method = options.delete(:generator) || SecureRandom.method(self.generator_method)
15
- token_size = options.delete(:size) || 32
16
- generator_method.call(token_size)
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.generator_method
22
- Doorkeeper.configuration.default_generator_method
24
+ def self.default_generator_method
25
+ Doorkeeper.config.default_generator_method
23
26
  end
24
27
  end
25
28
  end
@@ -18,17 +18,17 @@ module Doorkeeper
18
18
 
19
19
  # For backward compatibility with old rubies
20
20
  if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5.0")
21
- IPAddr.send(:include, Doorkeeper::IPAddrLoopback)
21
+ IPAddr.include Doorkeeper::IPAddrLoopback
22
22
  end
23
23
 
24
24
  module OAuth
25
25
  module Helpers
26
26
  module URIChecker
27
27
  def self.valid?(url)
28
- return true if native_uri?(url)
28
+ return true if oob_uri?(url)
29
29
 
30
30
  uri = as_uri(url)
31
- uri.fragment.nil? && !uri.host.nil? && !uri.scheme.nil?
31
+ valid_scheme?(uri) && iff_host?(uri) && uri.fragment.nil? && uri.opaque.nil?
32
32
  rescue URI::InvalidURIError
33
33
  false
34
34
  end
@@ -78,8 +78,22 @@ module Doorkeeper
78
78
  client_query.split("&").sort == query.split("&").sort
79
79
  end
80
80
 
81
- def self.native_uri?(url)
82
- url == Doorkeeper.configuration.native_redirect_uri
81
+ def self.valid_scheme?(uri)
82
+ return false if uri.scheme.nil?
83
+
84
+ %w[localhost].include?(uri.scheme) == false
85
+ end
86
+
87
+ def self.hypertext_scheme?(uri)
88
+ %w[http https].include?(uri.scheme)
89
+ end
90
+
91
+ def self.iff_host?(uri)
92
+ !(hypertext_scheme?(uri) && uri.host.nil?)
93
+ end
94
+
95
+ def self.oob_uri?(uri)
96
+ NonStandard::IETF_WG_OAUTH2_OOB_METHODS.include?(uri)
83
97
  end
84
98
  end
85
99
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class InvalidRequestResponse < ErrorResponse
6
+ attr_reader :reason
7
+
8
+ def self.from_request(request, attributes = {})
9
+ new(
10
+ attributes.merge(
11
+ state: request.try(:state),
12
+ redirect_uri: request.try(:redirect_uri),
13
+ missing_param: request.try(:missing_param),
14
+ reason: request.try(:invalid_request_reason),
15
+ ),
16
+ )
17
+ end
18
+
19
+ def initialize(attributes = {})
20
+ super(attributes.merge(name: :invalid_request))
21
+ @missing_param = attributes[:missing_param]
22
+ @reason = @missing_param.nil? ? attributes[:reason] : :missing_param
23
+ end
24
+
25
+ def status
26
+ :bad_request
27
+ end
28
+
29
+ def description
30
+ I18n.translate(
31
+ reason,
32
+ scope: %i[doorkeeper errors messages invalid_request],
33
+ default: :unknown,
34
+ value: @missing_param,
35
+ )
36
+ end
37
+
38
+ def redirectable?
39
+ super && @missing_param != :client_id
40
+ end
41
+ end
42
+ end
43
+ end
@@ -27,8 +27,11 @@ module Doorkeeper
27
27
  end
28
28
 
29
29
  def description
30
- scope = { scope: %i[doorkeeper errors messages invalid_token] }
31
- @description ||= I18n.translate @reason, scope
30
+ @description ||=
31
+ I18n.translate(
32
+ @reason,
33
+ scope: %i[doorkeeper errors messages invalid_token],
34
+ )
32
35
  end
33
36
 
34
37
  protected
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class NonStandard
6
+ # These are not part of the OAuth 2 specification but are still in use by Google
7
+ # and in some other implementations. Native applications should use one of the
8
+ # approaches discussed in RFC8252. OOB is 'Out of Band'
9
+
10
+ # This value signals to the Google Authorization Server that the authorization
11
+ # code should be returned in the title bar of the browser, with the page text
12
+ # prompting the user to copy the code and paste it in the application.
13
+ # This is useful when the client (such as a Windows application) cannot listen
14
+ # on an HTTP port without significant client configuration.
15
+
16
+ # When you use this value, your application can then detect that the page has loaded, and can
17
+ # read the title of the HTML page to obtain the authorization code. It is then up to your
18
+ # application to close the browser window if you want to ensure that the user never sees the
19
+ # page that contains the authorization code. The mechanism for doing this varies from platform
20
+ # to platform.
21
+ #
22
+ # If your platform doesn't allow you to detect that the page has loaded or read the title of
23
+ # the page, you can have the user paste the code back to your application, as prompted by the
24
+ # text in the confirmation page that the OAuth 2.0 server generates.
25
+ IETF_WG_OAUTH2_OOB = "urn:ietf:wg:oauth:2.0:oob"
26
+
27
+ # This is identical to urn:ietf:wg:oauth:2.0:oob, but the text in the confirmation page that
28
+ # the OAuth 2.0 server generates won't instruct the user to copy the authorization code, but
29
+ # instead will simply ask the user to close the window.
30
+ #
31
+ # This is useful when your application reads the title of the HTML page (by checking window
32
+ # titles on the desktop, for example) to obtain the authorization code, but can't close the
33
+ # page on its own.
34
+ IETF_WG_OAUTH2_OOB_AUTO = "urn:ietf:wg:oauth:2.0:oob:auto"
35
+
36
+ IETF_WG_OAUTH2_OOB_METHODS = [IETF_WG_OAUTH2_OOB, IETF_WG_OAUTH2_OOB_AUTO].freeze
37
+ end
38
+ end
39
+ end
@@ -5,9 +5,10 @@ module Doorkeeper
5
5
  class PasswordAccessTokenRequest < BaseRequest
6
6
  include OAuth::Helpers
7
7
 
8
- validate :client, error: :invalid_client
8
+ validate :client, error: :invalid_client
9
+ validate :client_supports_grant_flow, error: :unauthorized_client
9
10
  validate :resource_owner, error: :invalid_grant
10
- validate :scopes, error: :invalid_scope
11
+ validate :scopes, error: :invalid_scope
11
12
 
12
13
  attr_accessor :server, :client, :resource_owner, :parameters,
13
14
  :access_token
@@ -36,17 +37,21 @@ module Doorkeeper
36
37
  scope_str: scopes.to_s,
37
38
  server_scopes: server.scopes,
38
39
  app_scopes: client_scopes,
39
- grant_type: grant_type
40
+ grant_type: grant_type,
40
41
  )
41
42
  end
42
43
 
43
44
  def validate_resource_owner
44
- !resource_owner.nil?
45
+ resource_owner.present?
45
46
  end
46
47
 
47
48
  def validate_client
48
49
  !parameters[:client_id] || client.present?
49
50
  end
51
+
52
+ def validate_client_supports_grant_flow
53
+ server_config.allow_grant_flow_for_client?(grant_type, client)
54
+ end
50
55
  end
51
56
  end
52
57
  end
@@ -5,19 +5,21 @@ module Doorkeeper
5
5
  class PreAuthorization
6
6
  include Validations
7
7
 
8
- validate :response_type, error: :unsupported_response_type
9
- validate :client, error: :invalid_client
10
- validate :scopes, error: :invalid_scope
11
- validate :redirect_uri, error: :invalid_redirect_uri
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
12
14
  validate :code_challenge_method, error: :invalid_code_challenge_method
15
+ validate :client_supports_grant_flow, error: :unauthorized_client
13
16
 
14
- attr_accessor :server, :client, :response_type, :redirect_uri, :state,
15
- :code_challenge, :code_challenge_method
16
- attr_writer :scope
17
+ attr_reader :server, :client_id, :client, :redirect_uri, :response_type, :state,
18
+ :code_challenge, :code_challenge_method, :missing_param
17
19
 
18
- def initialize(server, client, attrs = {})
20
+ def initialize(server, attrs = {})
19
21
  @server = server
20
- @client = client
22
+ @client_id = attrs[:client_id]
21
23
  @response_type = attrs[:response_type]
22
24
  @redirect_uri = attrs[:redirect_uri]
23
25
  @scope = attrs[:scope]
@@ -30,34 +32,39 @@ module Doorkeeper
30
32
  valid?
31
33
  end
32
34
 
35
+ def validate_client_supports_grant_flow
36
+ Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client.application)
37
+ end
38
+
33
39
  def scopes
34
40
  Scopes.from_string scope
35
41
  end
36
42
 
37
43
  def scope
38
- @scope.presence || build_scopes
44
+ @scope.presence || (server.default_scopes.presence && build_scopes)
39
45
  end
40
46
 
41
47
  def error_response
42
- OAuth::ErrorResponse.from_request(self)
48
+ if error == :invalid_request
49
+ OAuth::InvalidRequestResponse.from_request(
50
+ self,
51
+ response_on_fragment: response_on_fragment?,
52
+ )
53
+ else
54
+ OAuth::ErrorResponse.from_request(self, response_on_fragment: response_on_fragment?)
55
+ end
43
56
  end
44
57
 
45
- def as_json(_options)
46
- {
47
- client_id: client.uid,
48
- redirect_uri: redirect_uri,
49
- state: state,
50
- response_type: response_type,
51
- scope: scope,
52
- client_name: client.name,
53
- status: I18n.t("doorkeeper.pre_authorization.status"),
54
- }
58
+ def as_json(attributes = {})
59
+ return pre_auth_hash.merge(attributes.to_h) if attributes.respond_to?(:to_h)
60
+
61
+ pre_auth_hash
55
62
  end
56
63
 
57
64
  private
58
65
 
59
66
  def build_scopes
60
- client_scopes = client.application.scopes
67
+ client_scopes = client.scopes
61
68
  if client_scopes.blank?
62
69
  server.default_scopes.to_s
63
70
  else
@@ -65,22 +72,46 @@ module Doorkeeper
65
72
  end
66
73
  end
67
74
 
68
- def validate_response_type
69
- server.authorization_response_types.include? response_type
75
+ def validate_client_id
76
+ @missing_param = :client_id if client_id.blank?
77
+
78
+ @missing_param.nil?
70
79
  end
71
80
 
72
81
  def validate_client
73
- client.present?
82
+ @client = OAuth::Client.find(client_id)
83
+ @client.present?
74
84
  end
75
85
 
76
- def validate_scopes
77
- return true if scope.blank?
86
+ def validate_redirect_uri
87
+ return false if redirect_uri.blank?
88
+
89
+ Helpers::URIChecker.valid_for_authorization?(
90
+ redirect_uri,
91
+ client.redirect_uri,
92
+ )
93
+ end
94
+
95
+ def validate_params
96
+ @missing_param = if response_type.blank?
97
+ :response_type
98
+ elsif @scope.blank? && server.default_scopes.blank?
99
+ :scope
100
+ end
101
+
102
+ @missing_param.nil?
103
+ end
104
+
105
+ def validate_response_type
106
+ server.authorization_response_types.include?(response_type)
107
+ end
78
108
 
109
+ def validate_scopes
79
110
  Helpers::ScopeChecker.valid?(
80
111
  scope_str: scope,
81
112
  server_scopes: server.scopes,
82
- app_scopes: client.application.scopes,
83
- grant_type: grant_type
113
+ app_scopes: client.scopes,
114
+ grant_type: grant_type,
84
115
  )
85
116
  end
86
117
 
@@ -88,19 +119,26 @@ module Doorkeeper
88
119
  response_type == "code" ? AUTHORIZATION_CODE : IMPLICIT
89
120
  end
90
121
 
91
- def validate_redirect_uri
92
- return false if redirect_uri.blank?
93
-
94
- Helpers::URIChecker.valid_for_authorization?(
95
- redirect_uri,
96
- client.redirect_uri
97
- )
98
- end
99
-
100
122
  def validate_code_challenge_method
101
123
  code_challenge.blank? ||
102
124
  (code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
103
125
  end
126
+
127
+ def response_on_fragment?
128
+ response_type == "token"
129
+ end
130
+
131
+ def pre_auth_hash
132
+ {
133
+ client_id: client.uid,
134
+ redirect_uri: redirect_uri,
135
+ state: state,
136
+ response_type: response_type,
137
+ scope: scope,
138
+ client_name: client.name,
139
+ status: I18n.t("doorkeeper.pre_authorization.status"),
140
+ }
141
+ end
104
142
  end
105
143
  end
106
144
  end
@@ -13,26 +13,27 @@ module Doorkeeper
13
13
 
14
14
  attr_accessor :access_token, :client, :credentials, :refresh_token,
15
15
  :server
16
+ attr_reader :missing_param
16
17
 
17
18
  def initialize(server, refresh_token, credentials, parameters = {})
18
- @server = server
19
- @refresh_token = refresh_token
20
- @credentials = credentials
19
+ @server = server
20
+ @refresh_token = refresh_token
21
+ @credentials = credentials
21
22
  @original_scopes = parameters[:scope] || parameters[:scopes]
22
23
  @refresh_token_parameter = parameters[:refresh_token]
23
-
24
- if credentials
25
- @client = Application.by_uid_and_secret credentials.uid,
26
- credentials.secret
27
- end
24
+ @client = load_client(credentials) if credentials
28
25
  end
29
26
 
30
27
  private
31
28
 
29
+ def load_client(credentials)
30
+ server_config.application_model.by_uid_and_secret(credentials.uid, credentials.secret)
31
+ end
32
+
32
33
  def before_successful_response
33
34
  refresh_token.transaction do
34
35
  refresh_token.lock!
35
- raise Errors::InvalidTokenReuse if refresh_token.revoked?
36
+ raise Errors::InvalidGrantReuse if refresh_token.revoked?
36
37
 
37
38
  refresh_token.revoke unless refresh_token_revoked_on_use?
38
39
  create_access_token
@@ -41,7 +42,7 @@ module Doorkeeper
41
42
  end
42
43
 
43
44
  def refresh_token_revoked_on_use?
44
- Doorkeeper::AccessToken.refresh_token_revoked_on_use?
45
+ server_config.access_token_model.refresh_token_revoked_on_use?
45
46
  end
46
47
 
47
48
  def default_scopes
@@ -49,7 +50,7 @@ module Doorkeeper
49
50
  end
50
51
 
51
52
  def create_access_token
52
- @access_token = AccessToken.create!(access_token_attributes)
53
+ @access_token = server_config.access_token_model.create!(access_token_attributes)
53
54
  end
54
55
 
55
56
  def access_token_attributes
@@ -70,13 +71,15 @@ module Doorkeeper
70
71
  context = Authorization::Token.build_context(
71
72
  client,
72
73
  Doorkeeper::OAuth::REFRESH_TOKEN,
73
- scopes
74
+ scopes,
74
75
  )
75
76
  Authorization::Token.access_token_expires_in(server, context)
76
77
  end
77
78
 
78
79
  def validate_token_presence
79
- refresh_token.present? || @refresh_token_parameter.present?
80
+ @missing_param = :refresh_token if refresh_token.blank? && @refresh_token_parameter.blank?
81
+
82
+ @missing_param.nil?
80
83
  end
81
84
 
82
85
  def validate_token
@@ -101,7 +104,7 @@ module Doorkeeper
101
104
  if @original_scopes.present?
102
105
  ScopeChecker.valid?(
103
106
  scope_str: @original_scopes,
104
- server_scopes: refresh_token.scopes
107
+ server_scopes: refresh_token.scopes,
105
108
  )
106
109
  else
107
110
  true
@@ -14,8 +14,8 @@ module Doorkeeper
14
14
 
15
15
  def authenticate(request, *methods)
16
16
  if (token = from_request(request, *methods))
17
- access_token = AccessToken.by_token(token)
18
- refresh_token_enabled = Doorkeeper.configuration.refresh_token_enabled?
17
+ access_token = Doorkeeper.config.access_token_model.by_token(token)
18
+ refresh_token_enabled = Doorkeeper.config.refresh_token_enabled?
19
19
  if access_token.present? && refresh_token_enabled
20
20
  access_token.revoke_previous_refresh_token!
21
21
  end