doorkeeper 5.2.2 → 5.5.4

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.

Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +198 -3
  3. data/README.md +28 -20
  4. data/app/controllers/doorkeeper/application_controller.rb +3 -2
  5. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -2
  6. data/app/controllers/doorkeeper/applications_controller.rb +7 -8
  7. data/app/controllers/doorkeeper/authorizations_controller.rb +48 -18
  8. data/app/controllers/doorkeeper/authorized_applications_controller.rb +6 -6
  9. data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
  10. data/app/controllers/doorkeeper/tokens_controller.rb +70 -25
  11. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  12. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  13. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  14. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  15. data/app/views/doorkeeper/authorizations/new.html.erb +2 -0
  16. data/config/locales/en.yml +9 -2
  17. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  18. data/lib/doorkeeper/config/option.rb +26 -14
  19. data/lib/doorkeeper/config/validations.rb +53 -0
  20. data/lib/doorkeeper/config.rb +214 -122
  21. data/lib/doorkeeper/engine.rb +1 -1
  22. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  23. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  24. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  25. data/lib/doorkeeper/grant_flow.rb +45 -0
  26. data/lib/doorkeeper/grape/helpers.rb +2 -2
  27. data/lib/doorkeeper/helpers/controller.rb +18 -12
  28. data/lib/doorkeeper/models/access_grant_mixin.rb +23 -19
  29. data/lib/doorkeeper/models/access_token_mixin.rb +157 -55
  30. data/lib/doorkeeper/models/application_mixin.rb +8 -7
  31. data/lib/doorkeeper/models/concerns/expirable.rb +1 -1
  32. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  33. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  34. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  35. data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
  36. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  37. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  38. data/lib/doorkeeper/oauth/authorization/code.rb +22 -9
  39. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  40. data/lib/doorkeeper/oauth/authorization/token.rb +23 -18
  41. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  42. data/lib/doorkeeper/oauth/authorization_code_request.rb +30 -20
  43. data/lib/doorkeeper/oauth/base_request.rb +19 -23
  44. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  45. data/lib/doorkeeper/oauth/client.rb +8 -9
  46. data/lib/doorkeeper/oauth/client_credentials/creator.rb +38 -12
  47. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
  48. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +7 -5
  49. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  50. data/lib/doorkeeper/oauth/code_request.rb +4 -4
  51. data/lib/doorkeeper/oauth/code_response.rb +24 -14
  52. data/lib/doorkeeper/oauth/error.rb +1 -1
  53. data/lib/doorkeeper/oauth/error_response.rb +10 -11
  54. data/lib/doorkeeper/oauth/forbidden_token_response.rb +2 -1
  55. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
  56. data/lib/doorkeeper/oauth/helpers/unique_token.rb +10 -7
  57. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -19
  58. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  59. data/lib/doorkeeper/oauth/invalid_request_response.rb +3 -3
  60. data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
  61. data/lib/doorkeeper/oauth/password_access_token_request.rb +28 -10
  62. data/lib/doorkeeper/oauth/pre_authorization.rb +73 -37
  63. data/lib/doorkeeper/oauth/refresh_token_request.rb +35 -26
  64. data/lib/doorkeeper/oauth/token.rb +6 -7
  65. data/lib/doorkeeper/oauth/token_introspection.rb +12 -16
  66. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  67. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  68. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  69. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  70. data/lib/doorkeeper/orm/active_record/application.rb +5 -95
  71. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +69 -0
  72. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +60 -0
  73. data/lib/doorkeeper/orm/active_record/mixins/application.rb +199 -0
  74. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +8 -3
  75. data/lib/doorkeeper/orm/active_record.rb +5 -7
  76. data/lib/doorkeeper/rails/helpers.rb +4 -4
  77. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  78. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  79. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  80. data/lib/doorkeeper/rails/routes.rb +17 -25
  81. data/lib/doorkeeper/rake/db.rake +6 -6
  82. data/lib/doorkeeper/rake/setup.rake +5 -0
  83. data/lib/doorkeeper/request/authorization_code.rb +3 -3
  84. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  85. data/lib/doorkeeper/request/password.rb +3 -2
  86. data/lib/doorkeeper/request/refresh_token.rb +5 -4
  87. data/lib/doorkeeper/request/strategy.rb +2 -2
  88. data/lib/doorkeeper/request.rb +49 -12
  89. data/lib/doorkeeper/server.rb +5 -5
  90. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  91. data/lib/doorkeeper/version.rb +2 -6
  92. data/lib/doorkeeper.rb +112 -81
  93. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  94. data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
  95. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  96. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  97. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  98. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +2 -2
  99. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  100. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  101. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  102. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  103. data/lib/generators/doorkeeper/templates/initializer.rb +99 -14
  104. data/lib/generators/doorkeeper/templates/migration.rb.erb +14 -5
  105. metadata +37 -306
  106. data/Appraisals +0 -40
  107. data/CODE_OF_CONDUCT.md +0 -46
  108. data/CONTRIBUTING.md +0 -49
  109. data/Dangerfile +0 -67
  110. data/Dockerfile +0 -29
  111. data/Gemfile +0 -25
  112. data/NEWS.md +0 -1
  113. data/RELEASING.md +0 -11
  114. data/Rakefile +0 -28
  115. data/SECURITY.md +0 -15
  116. data/UPGRADE.md +0 -2
  117. data/bin/console +0 -16
  118. data/doorkeeper.gemspec +0 -42
  119. data/gemfiles/rails_5_0.gemfile +0 -18
  120. data/gemfiles/rails_5_1.gemfile +0 -18
  121. data/gemfiles/rails_5_2.gemfile +0 -18
  122. data/gemfiles/rails_6_0.gemfile +0 -18
  123. data/gemfiles/rails_master.gemfile +0 -18
  124. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  125. data/spec/controllers/applications_controller_spec.rb +0 -273
  126. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  127. data/spec/controllers/protected_resources_controller_spec.rb +0 -353
  128. data/spec/controllers/token_info_controller_spec.rb +0 -50
  129. data/spec/controllers/tokens_controller_spec.rb +0 -498
  130. data/spec/dummy/Rakefile +0 -9
  131. data/spec/dummy/app/assets/config/manifest.js +0 -2
  132. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  133. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  134. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  135. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  136. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  137. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  138. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  139. data/spec/dummy/app/models/user.rb +0 -7
  140. data/spec/dummy/app/views/home/index.html.erb +0 -0
  141. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  142. data/spec/dummy/config/application.rb +0 -49
  143. data/spec/dummy/config/boot.rb +0 -7
  144. data/spec/dummy/config/database.yml +0 -15
  145. data/spec/dummy/config/environment.rb +0 -5
  146. data/spec/dummy/config/environments/development.rb +0 -31
  147. data/spec/dummy/config/environments/production.rb +0 -64
  148. data/spec/dummy/config/environments/test.rb +0 -45
  149. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  150. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  151. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  152. data/spec/dummy/config/initializers/session_store.rb +0 -10
  153. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  154. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  155. data/spec/dummy/config/routes.rb +0 -13
  156. data/spec/dummy/config.ru +0 -6
  157. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  158. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  159. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  160. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  161. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  162. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  163. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  164. data/spec/dummy/db/schema.rb +0 -68
  165. data/spec/dummy/public/404.html +0 -26
  166. data/spec/dummy/public/422.html +0 -26
  167. data/spec/dummy/public/500.html +0 -26
  168. data/spec/dummy/public/favicon.ico +0 -0
  169. data/spec/dummy/script/rails +0 -9
  170. data/spec/factories.rb +0 -30
  171. data/spec/generators/application_owner_generator_spec.rb +0 -28
  172. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  173. data/spec/generators/install_generator_spec.rb +0 -36
  174. data/spec/generators/migration_generator_spec.rb +0 -28
  175. data/spec/generators/pkce_generator_spec.rb +0 -28
  176. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  177. data/spec/generators/templates/routes.rb +0 -4
  178. data/spec/generators/views_generator_spec.rb +0 -29
  179. data/spec/grape/grape_integration_spec.rb +0 -137
  180. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  181. data/spec/lib/config_spec.rb +0 -739
  182. data/spec/lib/doorkeeper_spec.rb +0 -27
  183. data/spec/lib/models/expirable_spec.rb +0 -61
  184. data/spec/lib/models/reusable_spec.rb +0 -40
  185. data/spec/lib/models/revocable_spec.rb +0 -59
  186. data/spec/lib/models/scopes_spec.rb +0 -53
  187. data/spec/lib/models/secret_storable_spec.rb +0 -135
  188. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  189. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -168
  190. data/spec/lib/oauth/base_request_spec.rb +0 -222
  191. data/spec/lib/oauth/base_response_spec.rb +0 -47
  192. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  193. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -97
  194. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  195. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  196. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
  197. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
  198. data/spec/lib/oauth/client_spec.rb +0 -38
  199. data/spec/lib/oauth/code_request_spec.rb +0 -46
  200. data/spec/lib/oauth/code_response_spec.rb +0 -36
  201. data/spec/lib/oauth/error_response_spec.rb +0 -66
  202. data/spec/lib/oauth/error_spec.rb +0 -23
  203. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
  204. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
  205. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  206. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  207. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -75
  208. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
  209. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
  210. data/spec/lib/oauth/pre_authorization_spec.rb +0 -225
  211. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -178
  212. data/spec/lib/oauth/scopes_spec.rb +0 -148
  213. data/spec/lib/oauth/token_request_spec.rb +0 -153
  214. data/spec/lib/oauth/token_response_spec.rb +0 -86
  215. data/spec/lib/oauth/token_spec.rb +0 -158
  216. data/spec/lib/request/strategy_spec.rb +0 -54
  217. data/spec/lib/secret_storing/base_spec.rb +0 -60
  218. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  219. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  220. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  221. data/spec/lib/server_spec.rb +0 -49
  222. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  223. data/spec/models/doorkeeper/access_grant_spec.rb +0 -163
  224. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  225. data/spec/models/doorkeeper/application_spec.rb +0 -377
  226. data/spec/requests/applications/applications_request_spec.rb +0 -259
  227. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  228. data/spec/requests/endpoints/authorization_spec.rb +0 -89
  229. data/spec/requests/endpoints/token_spec.rb +0 -75
  230. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  231. data/spec/requests/flows/authorization_code_spec.rb +0 -513
  232. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  233. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  234. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  235. data/spec/requests/flows/password_spec.rb +0 -296
  236. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  237. data/spec/requests/flows/revoke_token_spec.rb +0 -151
  238. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  239. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  240. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  241. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  242. data/spec/routing/default_routes_spec.rb +0 -41
  243. data/spec/routing/scoped_routes_spec.rb +0 -47
  244. data/spec/spec_helper.rb +0 -57
  245. data/spec/spec_helper_integration.rb +0 -4
  246. data/spec/support/dependencies/factory_bot.rb +0 -4
  247. data/spec/support/doorkeeper_rspec.rb +0 -22
  248. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  249. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  250. data/spec/support/helpers/config_helper.rb +0 -11
  251. data/spec/support/helpers/model_helper.rb +0 -78
  252. data/spec/support/helpers/request_spec_helper.rb +0 -110
  253. data/spec/support/helpers/url_helper.rb +0 -62
  254. data/spec/support/http_method_shim.rb +0 -29
  255. data/spec/support/orm/active_record.rb +0 -5
  256. data/spec/support/shared/controllers_shared_context.rb +0 -123
  257. data/spec/support/shared/hashing_shared_context.rb +0 -36
  258. data/spec/support/shared/models_shared_examples.rb +0 -54
  259. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  260. data/spec/version/version_spec.rb +0 -17
@@ -3,17 +3,17 @@
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
- @pre_auth = pre_auth
9
+ @pre_auth = pre_auth
10
10
  @resource_owner = resource_owner
11
11
  end
12
12
 
13
13
  def authorize
14
14
  auth = Authorization::Code.new(pre_auth, resource_owner)
15
- auth.issue_token
16
- CodeResponse.new(pre_auth, auth)
15
+ auth.issue_token!
16
+ CodeResponse.new(pre_auth, auth, response_on_fragment: pre_auth.response_mode == "fragment")
17
17
  end
18
18
 
19
19
  def deny
@@ -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,23 +17,33 @@ module Doorkeeper
17
17
  true
18
18
  end
19
19
 
20
- def redirect_uri
21
- if URIChecker.oob_uri? pre_auth.redirect_uri
22
- auth.oob_redirect
23
- elsif response_on_fragment
24
- Authorization::URIBuilder.uri_with_fragment(
25
- pre_auth.redirect_uri,
20
+ def issued_token
21
+ auth.token
22
+ end
23
+
24
+ def body
25
+ if auth.try(:access_token?)
26
+ {
26
27
  access_token: auth.token.plaintext_token,
27
28
  token_type: auth.token.token_type,
28
29
  expires_in: auth.token.expires_in_seconds,
29
- state: pre_auth.state
30
- )
31
- else
32
- Authorization::URIBuilder.uri_with_query(
33
- pre_auth.redirect_uri,
30
+ state: pre_auth.state,
31
+ }
32
+ elsif auth.try(:access_grant?)
33
+ {
34
34
  code: auth.token.plaintext_token,
35
- state: pre_auth.state
36
- )
35
+ state: pre_auth.state,
36
+ }
37
+ end
38
+ end
39
+
40
+ def redirect_uri
41
+ if URIChecker.oob_uri?(pre_auth.redirect_uri)
42
+ auth.oob_redirect
43
+ elsif response_on_fragment
44
+ Authorization::URIBuilder.uri_with_fragment(pre_auth.redirect_uri, body)
45
+ else
46
+ Authorization::URIBuilder.uri_with_query(pre_auth.redirect_uri, body)
37
47
  end
38
48
  end
39
49
  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
@@ -5,13 +5,15 @@ module Doorkeeper
5
5
  class ErrorResponse < BaseResponse
6
6
  include OAuth::Helpers
7
7
 
8
+ NON_REDIRECTABLE_STATES = %i[invalid_redirect_uri invalid_client unauthorized_client].freeze
9
+
8
10
  def self.from_request(request, attributes = {})
9
11
  new(
10
12
  attributes.merge(
11
13
  name: request.error,
12
14
  state: request.try(:state),
13
- redirect_uri: request.try(:redirect_uri)
14
- )
15
+ redirect_uri: request.try(:redirect_uri),
16
+ ),
15
17
  )
16
18
  end
17
19
 
@@ -32,7 +34,7 @@ module Doorkeeper
32
34
  end
33
35
 
34
36
  def status
35
- if name == :invalid_client
37
+ if name == :invalid_client || name == :unauthorized_client
36
38
  :unauthorized
37
39
  else
38
40
  :bad_request
@@ -40,15 +42,14 @@ module Doorkeeper
40
42
  end
41
43
 
42
44
  def redirectable?
43
- name != :invalid_redirect_uri && name != :invalid_client &&
44
- !URIChecker.oob_uri?(@redirect_uri)
45
+ !NON_REDIRECTABLE_STATES.include?(name) && !URIChecker.oob_uri?(@redirect_uri)
45
46
  end
46
47
 
47
48
  def redirect_uri
48
49
  if @response_on_fragment
49
- Authorization::URIBuilder.uri_with_fragment @redirect_uri, body
50
+ Authorization::URIBuilder.uri_with_fragment(@redirect_uri, body)
50
51
  else
51
- Authorization::URIBuilder.uri_with_query @redirect_uri, body
52
+ Authorization::URIBuilder.uri_with_query(@redirect_uri, body)
52
53
  end
53
54
  end
54
55
 
@@ -67,10 +68,8 @@ module Doorkeeper
67
68
 
68
69
  protected
69
70
 
70
- delegate :realm, to: :configuration
71
-
72
- def configuration
73
- Doorkeeper.configuration
71
+ def realm
72
+ Doorkeeper.config.realm
74
73
  end
75
74
 
76
75
  def exception_class
@@ -23,7 +23,8 @@ module Doorkeeper
23
23
  end
24
24
 
25
25
  def description
26
- @description ||= @scopes.map { |s| I18n.t(s, scope: %i[doorkeeper scopes]) }.join("\n")
26
+ @description ||= I18n.t("doorkeeper.errors.messages.forbidden_token.missing_scope",
27
+ oauth_scopes: @scopes.map(&:to_s).join(" "),)
27
28
  end
28
29
 
29
30
  protected
@@ -12,9 +12,7 @@ module Doorkeeper
12
12
  @scope_str = scope_str
13
13
  @valid_scopes = valid_scopes(server_scopes, app_scopes)
14
14
 
15
- if grant_type
16
- @scopes_by_grant_type = Doorkeeper.configuration.scopes_by_grant_type[grant_type.to_sym]
17
- end
15
+ @scopes_by_grant_type = Doorkeeper.config.scopes_by_grant_type[grant_type.to_sym] if grant_type
18
16
  end
19
17
 
20
18
  def valid?
@@ -27,11 +25,7 @@ module Doorkeeper
27
25
  private
28
26
 
29
27
  def valid_scopes(server_scopes, app_scopes)
30
- if app_scopes.present?
31
- app_scopes
32
- else
33
- server_scopes
34
- end
28
+ app_scopes.presence || server_scopes
35
29
  end
36
30
 
37
31
  def permitted_to_grant_type?
@@ -43,10 +37,12 @@ module Doorkeeper
43
37
  end
44
38
 
45
39
  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?
40
+ Validator.new(
41
+ scope_str,
42
+ server_scopes,
43
+ app_scopes,
44
+ grant_type,
45
+ ).valid?
50
46
  end
51
47
  end
52
48
  end
@@ -3,23 +3,26 @@
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
9
12
  # 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) *"="
10
13
  #
11
- # @see https://tools.ietf.org/html/rfc6749#appendix-A.12
12
- # @see https://tools.ietf.org/html/rfc6750#section-2.1
14
+ # @see https://datatracker.ietf.org/doc/html/rfc6749#appendix-A.12
15
+ # @see https://datatracker.ietf.org/doc/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
@@ -3,24 +3,6 @@
3
3
  require "ipaddr"
4
4
 
5
5
  module Doorkeeper
6
- module IPAddrLoopback
7
- def loopback?
8
- case @family
9
- when Socket::AF_INET
10
- @addr & 0xff000000 == 0x7f000000
11
- when Socket::AF_INET6
12
- @addr == 1
13
- else
14
- raise AddressFamilyError, "unsupported address family"
15
- end
16
- end
17
- end
18
-
19
- # For backward compatibility with old rubies
20
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5.0")
21
- IPAddr.send(:include, Doorkeeper::IPAddrLoopback)
22
- end
23
-
24
6
  module OAuth
25
7
  module Helpers
26
8
  module URIChecker
@@ -46,7 +28,7 @@ module Doorkeeper
46
28
  end
47
29
 
48
30
  # RFC8252, Paragraph 7.3
49
- # @see https://tools.ietf.org/html/rfc8252#section-7.3
31
+ # @see https://datatracker.ietf.org/doc/html/rfc8252#section-7.3
50
32
  if loopback_uri?(url) && loopback_uri?(client_url)
51
33
  url.port = nil
52
34
  client_url.port = nil
@@ -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
@@ -11,8 +11,8 @@ module Doorkeeper
11
11
  state: request.try(:state),
12
12
  redirect_uri: request.try(:redirect_uri),
13
13
  missing_param: request.try(:missing_param),
14
- reason: request.try(:invalid_request_reason)
15
- )
14
+ reason: request.try(:invalid_request_reason),
15
+ ),
16
16
  )
17
17
  end
18
18
 
@@ -31,7 +31,7 @@ module Doorkeeper
31
31
  reason,
32
32
  scope: %i[doorkeeper errors messages invalid_request],
33
33
  default: :unknown,
34
- value: @missing_param
34
+ value: @missing_param,
35
35
  )
36
36
  end
37
37
 
@@ -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
@@ -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
@@ -10,13 +10,13 @@ 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, :credentials, :resource_owner, :parameters, :access_token
15
14
 
16
- def initialize(server, client, resource_owner, parameters = {})
15
+ def initialize(server, client, credentials, resource_owner, parameters = {})
17
16
  @server = server
18
17
  @resource_owner = resource_owner
19
18
  @client = client
19
+ @credentials = credentials
20
20
  @parameters = parameters
21
21
  @original_scopes = parameters[:scope]
22
22
  @grant_type = Doorkeeper::OAuth::PASSWORD
@@ -25,32 +25,50 @@ module Doorkeeper
25
25
  private
26
26
 
27
27
  def before_successful_response
28
- find_or_create_access_token(client, resource_owner.id, scopes, server)
28
+ find_or_create_access_token(client, resource_owner, scopes, server)
29
29
  super
30
30
  end
31
31
 
32
32
  def validate_scopes
33
- client_scopes = client.try(:scopes)
34
33
  return true if scopes.blank?
35
34
 
36
35
  ScopeChecker.valid?(
37
36
  scope_str: scopes.to_s,
38
37
  server_scopes: server.scopes,
39
- app_scopes: client_scopes,
40
- grant_type: grant_type
38
+ app_scopes: client.try(:scopes),
39
+ grant_type: grant_type,
41
40
  )
42
41
  end
43
42
 
44
43
  def validate_resource_owner
45
- !resource_owner.nil?
44
+ resource_owner.present?
46
45
  end
47
46
 
47
+ # Section 4.3.2. Access Token Request for Resource Owner Password Credentials Grant:
48
+ #
49
+ # If the client type is confidential or the client was issued client credentials (or assigned
50
+ # other authentication requirements), the client MUST authenticate with the authorization
51
+ # server as described in Section 3.2.1.
52
+ #
53
+ # The authorization server MUST:
54
+ #
55
+ # o require client authentication for confidential clients or for any client that was
56
+ # issued client credentials (or with other authentication requirements)
57
+ #
58
+ # o authenticate the client if client authentication is included,
59
+ #
60
+ # @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3
61
+ #
48
62
  def validate_client
49
- !parameters[:client_id] || client.present?
63
+ if Doorkeeper.config.skip_client_authentication_for_password_grant
64
+ client.present? || (!parameters[:client_id] && credentials.blank?)
65
+ else
66
+ client.present?
67
+ end
50
68
  end
51
69
 
52
70
  def validate_client_supports_grant_flow
53
- Doorkeeper.configuration.allow_grant_flow_for_client?(grant_type, client)
71
+ server_config.allow_grant_flow_for_client?(grant_type, client&.application)
54
72
  end
55
73
  end
56
74
  end
@@ -5,39 +5,40 @@ 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
14
- validate :code_challenge_method, error: :invalid_code_challenge_method
8
+ validate :client_id, error: :invalid_request
9
+ validate :client, error: :invalid_client
15
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
16
18
 
17
- attr_reader :server, :client_id, :client, :redirect_uri, :response_type, :state,
18
- :code_challenge, :code_challenge_method, :missing_param
19
+ attr_reader :client, :code_challenge, :code_challenge_method, :missing_param,
20
+ :redirect_uri, :resource_owner, :response_type, :state,
21
+ :authorization_response_flow, :response_mode
19
22
 
20
- def initialize(server, attrs = {})
23
+ def initialize(server, parameters = {}, resource_owner = nil)
21
24
  @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]
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
+ @code_challenge_method = parameters[:code_challenge_method]
33
+ @resource_owner = resource_owner
29
34
  end
30
35
 
31
36
  def authorizable?
32
37
  valid?
33
38
  end
34
39
 
35
- def validate_client_supports_grant_flow
36
- Doorkeeper.configuration.allow_grant_flow_for_client?(grant_type, client.application)
37
- end
38
-
39
40
  def scopes
40
- Scopes.from_string scope
41
+ Scopes.from_string(scope)
41
42
  end
42
43
 
43
44
  def scope
@@ -45,23 +46,28 @@ module Doorkeeper
45
46
  end
46
47
 
47
48
  def error_response
48
- is_implicit_flow = response_type == "token"
49
-
50
49
  if error == :invalid_request
51
- OAuth::InvalidRequestResponse.from_request(self, response_on_fragment: is_implicit_flow)
50
+ OAuth::InvalidRequestResponse.from_request(
51
+ self,
52
+ response_on_fragment: response_on_fragment?,
53
+ )
52
54
  else
53
- OAuth::ErrorResponse.from_request(self, response_on_fragment: is_implicit_flow)
55
+ OAuth::ErrorResponse.from_request(self, response_on_fragment: response_on_fragment?)
54
56
  end
55
57
  end
56
58
 
57
- def as_json(attributes = {})
58
- return pre_auth_hash.merge(attributes.to_h) if attributes.respond_to?(:to_h)
59
-
59
+ def as_json(_options = nil)
60
60
  pre_auth_hash
61
61
  end
62
62
 
63
+ def form_post_response?
64
+ response_mode == "form_post"
65
+ end
66
+
63
67
  private
64
68
 
69
+ attr_reader :client_id, :server
70
+
65
71
  def build_scopes
66
72
  client_scopes = client.scopes
67
73
  if client_scopes.blank?
@@ -73,7 +79,6 @@ module Doorkeeper
73
79
 
74
80
  def validate_client_id
75
81
  @missing_param = :client_id if client_id.blank?
76
-
77
82
  @missing_param.nil?
78
83
  end
79
84
 
@@ -82,12 +87,21 @@ module Doorkeeper
82
87
  @client.present?
83
88
  end
84
89
 
90
+ def validate_client_supports_grant_flow
91
+ Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client.application)
92
+ end
93
+
94
+ def validate_resource_owner_authorize_for_client
95
+ # The `authorize_resource_owner_for_client` config option is used for this validation
96
+ client.application.authorized_for_resource_owner?(@resource_owner)
97
+ end
98
+
85
99
  def validate_redirect_uri
86
100
  return false if redirect_uri.blank?
87
101
 
88
102
  Helpers::URIChecker.valid_for_authorization?(
89
103
  redirect_uri,
90
- client.redirect_uri
104
+ client.redirect_uri,
91
105
  )
92
106
  end
93
107
 
@@ -102,7 +116,21 @@ module Doorkeeper
102
116
  end
103
117
 
104
118
  def validate_response_type
105
- server.authorization_response_types.include?(response_type)
119
+ server.authorization_response_flows.any? do |flow|
120
+ if flow.matches_response_type?(response_type)
121
+ @authorization_response_flow = flow
122
+ true
123
+ end
124
+ end
125
+ end
126
+
127
+ def validate_response_mode
128
+ if response_mode.blank?
129
+ @response_mode = authorization_response_flow.default_response_mode
130
+ return true
131
+ end
132
+
133
+ authorization_response_flow.matches_response_mode?(response_mode)
106
134
  end
107
135
 
108
136
  def validate_scopes
@@ -110,19 +138,27 @@ module Doorkeeper
110
138
  scope_str: scope,
111
139
  server_scopes: server.scopes,
112
140
  app_scopes: client.scopes,
113
- grant_type: grant_type
141
+ grant_type: grant_type,
114
142
  )
115
143
  end
116
144
 
117
- def grant_type
118
- response_type == "code" ? AUTHORIZATION_CODE : IMPLICIT
119
- end
120
-
121
145
  def validate_code_challenge_method
146
+ return true unless Doorkeeper.config.access_grant_model.pkce_supported?
147
+
122
148
  code_challenge.blank? ||
123
149
  (code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
124
150
  end
125
151
 
152
+ def response_on_fragment?
153
+ return response_type == "token" if response_mode.nil?
154
+
155
+ response_mode == "fragment"
156
+ end
157
+
158
+ def grant_type
159
+ response_type == "code" ? AUTHORIZATION_CODE : IMPLICIT
160
+ end
161
+
126
162
  def pre_auth_hash
127
163
  {
128
164
  client_id: client.uid,