doorkeeper 4.4.3 → 5.5.2

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 (282) hide show
  1. checksums.yaml +5 -5
  2. data/{NEWS.md → CHANGELOG.md} +393 -19
  3. data/README.md +97 -393
  4. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  5. data/app/controllers/doorkeeper/application_controller.rb +8 -5
  6. data/app/controllers/doorkeeper/application_metal_controller.rb +7 -11
  7. data/app/controllers/doorkeeper/applications_controller.rb +62 -27
  8. data/app/controllers/doorkeeper/authorizations_controller.rb +97 -17
  9. data/app/controllers/doorkeeper/authorized_applications_controller.rb +22 -3
  10. data/app/controllers/doorkeeper/token_info_controller.rb +16 -4
  11. data/app/controllers/doorkeeper/tokens_controller.rb +98 -32
  12. data/app/helpers/doorkeeper/dashboard_helper.rb +9 -7
  13. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  14. data/app/views/doorkeeper/applications/_form.html.erb +27 -26
  15. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  16. data/app/views/doorkeeper/applications/index.html.erb +17 -7
  17. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  18. data/app/views/doorkeeper/applications/show.html.erb +38 -17
  19. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  20. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  21. data/app/views/doorkeeper/authorizations/new.html.erb +6 -0
  22. data/app/views/layouts/doorkeeper/admin.html.erb +16 -14
  23. data/config/locales/en.yml +23 -3
  24. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  25. data/lib/doorkeeper/config/option.rb +82 -0
  26. data/lib/doorkeeper/config/validations.rb +53 -0
  27. data/lib/doorkeeper/config.rb +471 -140
  28. data/lib/doorkeeper/engine.rb +8 -2
  29. data/lib/doorkeeper/errors.rb +25 -16
  30. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  31. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  32. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  33. data/lib/doorkeeper/grant_flow.rb +45 -0
  34. data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
  35. data/lib/doorkeeper/grape/helpers.rb +13 -7
  36. data/lib/doorkeeper/helpers/controller.rb +43 -10
  37. data/lib/doorkeeper/models/access_grant_mixin.rb +97 -3
  38. data/lib/doorkeeper/models/access_token_mixin.rb +272 -66
  39. data/lib/doorkeeper/models/application_mixin.rb +50 -5
  40. data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
  41. data/lib/doorkeeper/models/concerns/expirable.rb +7 -3
  42. data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
  43. data/lib/doorkeeper/models/concerns/ownership.rb +4 -7
  44. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  45. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  46. data/lib/doorkeeper/models/concerns/revocable.rb +3 -27
  47. data/lib/doorkeeper/models/concerns/scopes.rb +12 -2
  48. data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
  49. data/lib/doorkeeper/oauth/authorization/code.rb +48 -12
  50. data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  51. data/lib/doorkeeper/oauth/authorization/token.rb +58 -24
  52. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +7 -5
  53. data/lib/doorkeeper/oauth/authorization_code_request.rb +58 -10
  54. data/lib/doorkeeper/oauth/base_request.rb +35 -24
  55. data/lib/doorkeeper/oauth/base_response.rb +2 -0
  56. data/lib/doorkeeper/oauth/client/credentials.rb +5 -5
  57. data/lib/doorkeeper/oauth/client.rb +10 -11
  58. data/lib/doorkeeper/oauth/client_credentials/creator.rb +47 -4
  59. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +16 -9
  60. data/lib/doorkeeper/oauth/client_credentials/validator.rb +56 -0
  61. data/lib/doorkeeper/oauth/client_credentials_request.rb +10 -11
  62. data/lib/doorkeeper/oauth/code_request.rb +8 -12
  63. data/lib/doorkeeper/oauth/code_response.rb +27 -15
  64. data/lib/doorkeeper/oauth/error.rb +3 -1
  65. data/lib/doorkeeper/oauth/error_response.rb +35 -14
  66. data/lib/doorkeeper/oauth/forbidden_token_response.rb +10 -3
  67. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -18
  68. data/lib/doorkeeper/oauth/helpers/unique_token.rb +20 -3
  69. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +42 -7
  70. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  71. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  72. data/lib/doorkeeper/oauth/invalid_token_response.rb +29 -4
  73. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  74. data/lib/doorkeeper/oauth/password_access_token_request.rb +43 -10
  75. data/lib/doorkeeper/oauth/pre_authorization.rb +133 -26
  76. data/lib/doorkeeper/oauth/refresh_token_request.rb +59 -31
  77. data/lib/doorkeeper/oauth/scopes.rb +8 -4
  78. data/lib/doorkeeper/oauth/token.rb +12 -8
  79. data/lib/doorkeeper/oauth/token_introspection.rb +97 -23
  80. data/lib/doorkeeper/oauth/token_request.rb +8 -20
  81. data/lib/doorkeeper/oauth/token_response.rb +14 -10
  82. data/lib/doorkeeper/oauth.rb +13 -0
  83. data/lib/doorkeeper/orm/active_record/access_grant.rb +5 -30
  84. data/lib/doorkeeper/orm/active_record/access_token.rb +5 -43
  85. data/lib/doorkeeper/orm/active_record/application.rb +6 -57
  86. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +68 -0
  87. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +59 -0
  88. data/lib/doorkeeper/orm/active_record/mixins/application.rb +198 -0
  89. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  90. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +33 -0
  91. data/lib/doorkeeper/orm/active_record.rb +27 -9
  92. data/lib/doorkeeper/rails/helpers.rb +10 -8
  93. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  94. data/lib/doorkeeper/rails/routes/mapper.rb +4 -2
  95. data/lib/doorkeeper/rails/routes/mapping.rb +9 -7
  96. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  97. data/lib/doorkeeper/rails/routes.rb +37 -30
  98. data/lib/doorkeeper/rake/db.rake +40 -0
  99. data/lib/doorkeeper/rake/setup.rake +11 -0
  100. data/lib/doorkeeper/rake.rb +14 -0
  101. data/lib/doorkeeper/request/authorization_code.rb +6 -4
  102. data/lib/doorkeeper/request/client_credentials.rb +3 -3
  103. data/lib/doorkeeper/request/code.rb +1 -1
  104. data/lib/doorkeeper/request/password.rb +4 -3
  105. data/lib/doorkeeper/request/refresh_token.rb +6 -5
  106. data/lib/doorkeeper/request/strategy.rb +4 -2
  107. data/lib/doorkeeper/request/token.rb +1 -1
  108. data/lib/doorkeeper/request.rb +61 -34
  109. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  110. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  111. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  112. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  113. data/lib/doorkeeper/server.rb +9 -11
  114. data/lib/doorkeeper/stale_records_cleaner.rb +24 -0
  115. data/lib/doorkeeper/validations.rb +2 -0
  116. data/lib/doorkeeper/version.rb +7 -29
  117. data/lib/doorkeeper.rb +111 -64
  118. data/lib/generators/doorkeeper/application_owner_generator.rb +24 -18
  119. data/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
  120. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  121. data/lib/generators/doorkeeper/install_generator.rb +19 -9
  122. data/lib/generators/doorkeeper/migration_generator.rb +23 -18
  123. data/lib/generators/doorkeeper/pkce_generator.rb +33 -0
  124. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +28 -22
  125. data/{spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb → lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb} +2 -2
  126. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  127. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  128. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
  129. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  130. data/lib/generators/doorkeeper/templates/initializer.rb +382 -30
  131. data/lib/generators/doorkeeper/templates/migration.rb.erb +35 -16
  132. data/lib/generators/doorkeeper/views_generator.rb +8 -4
  133. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  134. metadata +95 -309
  135. data/.coveralls.yml +0 -1
  136. data/.github/ISSUE_TEMPLATE.md +0 -25
  137. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  138. data/.gitignore +0 -19
  139. data/.hound.yml +0 -2
  140. data/.rspec +0 -1
  141. data/.rubocop.yml +0 -17
  142. data/.travis.yml +0 -38
  143. data/Appraisals +0 -18
  144. data/CODE_OF_CONDUCT.md +0 -46
  145. data/CONTRIBUTING.md +0 -47
  146. data/Gemfile +0 -10
  147. data/RELEASING.md +0 -10
  148. data/Rakefile +0 -20
  149. data/SECURITY.md +0 -15
  150. data/app/validators/redirect_uri_validator.rb +0 -44
  151. data/doorkeeper.gemspec +0 -32
  152. data/gemfiles/rails_4_2.gemfile +0 -13
  153. data/gemfiles/rails_5_0.gemfile +0 -12
  154. data/gemfiles/rails_5_1.gemfile +0 -12
  155. data/gemfiles/rails_5_2.gemfile +0 -12
  156. data/gemfiles/rails_master.gemfile +0 -14
  157. data/lib/doorkeeper/oauth/client_credentials/validation.rb +0 -45
  158. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
  159. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
  160. data/spec/controllers/application_metal_controller.rb +0 -10
  161. data/spec/controllers/applications_controller_spec.rb +0 -69
  162. data/spec/controllers/authorizations_controller_spec.rb +0 -250
  163. data/spec/controllers/protected_resources_controller_spec.rb +0 -309
  164. data/spec/controllers/token_info_controller_spec.rb +0 -56
  165. data/spec/controllers/tokens_controller_spec.rb +0 -274
  166. data/spec/dummy/Rakefile +0 -7
  167. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  168. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -7
  169. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -12
  170. data/spec/dummy/app/controllers/home_controller.rb +0 -17
  171. data/spec/dummy/app/controllers/metal_controller.rb +0 -11
  172. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -11
  173. data/spec/dummy/app/helpers/application_helper.rb +0 -5
  174. data/spec/dummy/app/models/user.rb +0 -5
  175. data/spec/dummy/app/views/home/index.html.erb +0 -0
  176. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  177. data/spec/dummy/config/application.rb +0 -23
  178. data/spec/dummy/config/boot.rb +0 -9
  179. data/spec/dummy/config/database.yml +0 -15
  180. data/spec/dummy/config/environment.rb +0 -5
  181. data/spec/dummy/config/environments/development.rb +0 -29
  182. data/spec/dummy/config/environments/production.rb +0 -62
  183. data/spec/dummy/config/environments/test.rb +0 -44
  184. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  185. data/spec/dummy/config/initializers/doorkeeper.rb +0 -112
  186. data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -6
  187. data/spec/dummy/config/initializers/secret_token.rb +0 -8
  188. data/spec/dummy/config/initializers/session_store.rb +0 -8
  189. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  190. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  191. data/spec/dummy/config/routes.rb +0 -52
  192. data/spec/dummy/config.ru +0 -4
  193. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  194. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  195. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -62
  196. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  197. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  198. data/spec/dummy/db/schema.rb +0 -68
  199. data/spec/dummy/public/404.html +0 -26
  200. data/spec/dummy/public/422.html +0 -26
  201. data/spec/dummy/public/500.html +0 -26
  202. data/spec/dummy/public/favicon.ico +0 -0
  203. data/spec/dummy/script/rails +0 -6
  204. data/spec/factories.rb +0 -28
  205. data/spec/generators/application_owner_generator_spec.rb +0 -41
  206. data/spec/generators/install_generator_spec.rb +0 -31
  207. data/spec/generators/migration_generator_spec.rb +0 -41
  208. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -57
  209. data/spec/generators/templates/routes.rb +0 -3
  210. data/spec/generators/views_generator_spec.rb +0 -27
  211. data/spec/grape/grape_integration_spec.rb +0 -135
  212. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -24
  213. data/spec/lib/config_spec.rb +0 -462
  214. data/spec/lib/doorkeeper_spec.rb +0 -150
  215. data/spec/lib/models/expirable_spec.rb +0 -50
  216. data/spec/lib/models/revocable_spec.rb +0 -59
  217. data/spec/lib/models/scopes_spec.rb +0 -43
  218. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -41
  219. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -123
  220. data/spec/lib/oauth/base_request_spec.rb +0 -155
  221. data/spec/lib/oauth/base_response_spec.rb +0 -45
  222. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  223. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -44
  224. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -86
  225. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -54
  226. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  227. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -105
  228. data/spec/lib/oauth/client_spec.rb +0 -39
  229. data/spec/lib/oauth/code_request_spec.rb +0 -43
  230. data/spec/lib/oauth/code_response_spec.rb +0 -34
  231. data/spec/lib/oauth/error_response_spec.rb +0 -61
  232. data/spec/lib/oauth/error_spec.rb +0 -23
  233. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -23
  234. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -64
  235. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -20
  236. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -218
  237. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -56
  238. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -96
  239. data/spec/lib/oauth/pre_authorization_spec.rb +0 -160
  240. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -166
  241. data/spec/lib/oauth/scopes_spec.rb +0 -149
  242. data/spec/lib/oauth/token_request_spec.rb +0 -96
  243. data/spec/lib/oauth/token_response_spec.rb +0 -85
  244. data/spec/lib/oauth/token_spec.rb +0 -116
  245. data/spec/lib/request/strategy_spec.rb +0 -53
  246. data/spec/lib/server_spec.rb +0 -59
  247. data/spec/models/doorkeeper/access_grant_spec.rb +0 -36
  248. data/spec/models/doorkeeper/access_token_spec.rb +0 -418
  249. data/spec/models/doorkeeper/application_spec.rb +0 -303
  250. data/spec/requests/applications/applications_request_spec.rb +0 -94
  251. data/spec/requests/applications/authorized_applications_spec.rb +0 -30
  252. data/spec/requests/endpoints/authorization_spec.rb +0 -71
  253. data/spec/requests/endpoints/token_spec.rb +0 -71
  254. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -76
  255. data/spec/requests/flows/authorization_code_spec.rb +0 -149
  256. data/spec/requests/flows/client_credentials_spec.rb +0 -86
  257. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -32
  258. data/spec/requests/flows/implicit_grant_spec.rb +0 -61
  259. data/spec/requests/flows/password_spec.rb +0 -197
  260. data/spec/requests/flows/refresh_token_spec.rb +0 -174
  261. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  262. data/spec/requests/flows/skip_authorization_spec.rb +0 -59
  263. data/spec/requests/protected_resources/metal_spec.rb +0 -14
  264. data/spec/requests/protected_resources/private_api_spec.rb +0 -81
  265. data/spec/routing/custom_controller_routes_spec.rb +0 -75
  266. data/spec/routing/default_routes_spec.rb +0 -39
  267. data/spec/routing/scoped_routes_spec.rb +0 -31
  268. data/spec/spec_helper.rb +0 -4
  269. data/spec/spec_helper_integration.rb +0 -74
  270. data/spec/support/dependencies/factory_girl.rb +0 -2
  271. data/spec/support/helpers/access_token_request_helper.rb +0 -11
  272. data/spec/support/helpers/authorization_request_helper.rb +0 -41
  273. data/spec/support/helpers/config_helper.rb +0 -9
  274. data/spec/support/helpers/model_helper.rb +0 -72
  275. data/spec/support/helpers/request_spec_helper.rb +0 -88
  276. data/spec/support/helpers/url_helper.rb +0 -56
  277. data/spec/support/http_method_shim.rb +0 -38
  278. data/spec/support/orm/active_record.rb +0 -3
  279. data/spec/support/shared/controllers_shared_context.rb +0 -65
  280. data/spec/support/shared/models_shared_examples.rb +0 -52
  281. data/spec/validators/redirect_uri_validator_spec.rb +0 -123
  282. data/spec/version/version_spec.rb +0 -15
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ module Authorization
6
+ class Context
7
+ attr_reader :client, :grant_type, :resource_owner, :scopes
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
+ end
15
+ end
16
+ end
17
+ end
@@ -1,28 +1,46 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  module Authorization
4
6
  class Token
5
- attr_accessor :pre_auth, :resource_owner, :token
7
+ attr_reader :pre_auth, :resource_owner, :token
6
8
 
7
9
  class << self
8
- def access_token_expires_in(server, pre_auth_or_oauth_client)
9
- if (expiration = custom_expiration(server, pre_auth_or_oauth_client))
10
- expiration
11
- else
12
- server.access_token_expires_in
13
- end
14
- end
15
-
16
- private
17
-
18
- def custom_expiration(server, pre_auth_or_oauth_client)
19
- oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
10
+ def build_context(pre_auth_or_oauth_client, grant_type, scopes, resource_owner)
11
+ oauth_client = if pre_auth_or_oauth_client.respond_to?(:application)
12
+ pre_auth_or_oauth_client.application
13
+ elsif pre_auth_or_oauth_client.respond_to?(:client)
20
14
  pre_auth_or_oauth_client.client
21
15
  else
22
16
  pre_auth_or_oauth_client
23
17
  end
24
18
 
25
- server.custom_access_token_expires_in.call(oauth_client)
19
+ Doorkeeper::OAuth::Authorization::Context.new(
20
+ client: oauth_client,
21
+ grant_type: grant_type,
22
+ scopes: scopes,
23
+ resource_owner: resource_owner,
24
+ )
25
+ end
26
+
27
+ def access_token_expires_in(configuration, context)
28
+ if configuration.option_defined?(:custom_access_token_expires_in)
29
+ expiration = configuration.custom_access_token_expires_in.call(context)
30
+ return nil if expiration == Float::INFINITY
31
+
32
+ expiration || configuration.access_token_expires_in
33
+ else
34
+ configuration.access_token_expires_in
35
+ end
36
+ end
37
+
38
+ def refresh_token_enabled?(server, context)
39
+ if server.refresh_token_enabled?.respond_to?(:call)
40
+ server.refresh_token_enabled?.call(context)
41
+ else
42
+ !!server.refresh_token_enabled?
43
+ end
26
44
  end
27
45
  end
28
46
 
@@ -31,28 +49,44 @@ module Doorkeeper
31
49
  @resource_owner = resource_owner
32
50
  end
33
51
 
34
- def issue_token
35
- @token ||= AccessToken.find_or_create_for(
52
+ def issue_token!
53
+ return @token if defined?(@token)
54
+
55
+ context = self.class.build_context(
36
56
  pre_auth.client,
37
- resource_owner.id,
57
+ Doorkeeper::OAuth::IMPLICIT,
38
58
  pre_auth.scopes,
39
- self.class.access_token_expires_in(configuration, pre_auth),
40
- false
59
+ resource_owner,
60
+ )
61
+
62
+ @token = Doorkeeper.config.access_token_model.find_or_create_for(
63
+ application: pre_auth.client,
64
+ resource_owner: resource_owner,
65
+ scopes: pre_auth.scopes,
66
+ expires_in: self.class.access_token_expires_in(Doorkeeper.config, context),
67
+ use_refresh_token: false,
41
68
  )
42
69
  end
43
70
 
44
- def native_redirect
71
+ def oob_redirect
45
72
  {
46
- controller: 'doorkeeper/token_info',
73
+ controller: controller,
47
74
  action: :show,
48
- access_token: token.token
75
+ access_token: token.plaintext_token,
49
76
  }
50
77
  end
51
78
 
79
+ def access_token?
80
+ true
81
+ end
82
+
52
83
  private
53
84
 
54
- def configuration
55
- Doorkeeper.configuration
85
+ def controller
86
+ @controller ||= begin
87
+ mapping = Doorkeeper::Rails::Routes.mapping[:token_info] || {}
88
+ mapping[:controllers] || "doorkeeper/token_info"
89
+ end
56
90
  end
57
91
  end
58
92
  end
@@ -1,4 +1,6 @@
1
- require 'rack/utils'
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/utils"
2
4
 
3
5
  module Doorkeeper
4
6
  module OAuth
@@ -6,9 +8,9 @@ module Doorkeeper
6
8
  class URIBuilder
7
9
  class << self
8
10
  def uri_with_query(url, parameters = {})
9
- uri = URI.parse(url)
11
+ uri = URI.parse(url)
10
12
  original_query = Rack::Utils.parse_query(uri.query)
11
- uri.query = build_query(original_query.merge(parameters))
13
+ uri.query = build_query(original_query.merge(parameters))
12
14
  uri.to_s
13
15
  end
14
16
 
@@ -21,8 +23,8 @@ module Doorkeeper
21
23
  private
22
24
 
23
25
  def build_query(parameters = {})
24
- parameters = parameters.reject { |_, v| v.blank? }
25
- Rack::Utils.build_query parameters
26
+ parameters.reject! { |_, value| value.blank? }
27
+ Rack::Utils.build_query(parameters)
26
28
  end
27
29
  end
28
30
  end
@@ -1,19 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class AuthorizationCodeRequest < BaseRequest
4
- validate :attributes, error: :invalid_request
6
+ validate :params, error: :invalid_request
5
7
  validate :client, error: :invalid_client
6
8
  validate :grant, error: :invalid_grant
7
9
  # @see https://tools.ietf.org/html/rfc6749#section-5.2
8
10
  validate :redirect_uri, error: :invalid_grant
11
+ validate :code_verifier, error: :invalid_grant
9
12
 
10
- attr_accessor :server, :grant, :client, :redirect_uri, :access_token
13
+ attr_reader :grant, :client, :redirect_uri, :access_token, :code_verifier,
14
+ :invalid_request_reason, :missing_param
11
15
 
12
16
  def initialize(server, grant, client, parameters = {})
13
17
  @server = server
14
18
  @client = client
15
19
  @grant = grant
20
+ @grant_type = Doorkeeper::OAuth::AUTHORIZATION_CODE
16
21
  @redirect_uri = parameters[:redirect_uri]
22
+ @code_verifier = parameters[:code_verifier]
17
23
  end
18
24
 
19
25
  private
@@ -24,33 +30,75 @@ module Doorkeeper
24
30
  raise Errors::InvalidGrantReuse if grant.revoked?
25
31
 
26
32
  grant.revoke
27
- find_or_create_access_token(grant.application,
28
- grant.resource_owner_id,
29
- grant.scopes,
30
- server)
33
+
34
+ find_or_create_access_token(
35
+ grant.application,
36
+ resource_owner,
37
+ grant.scopes,
38
+ server,
39
+ )
31
40
  end
41
+
32
42
  super
33
43
  end
34
44
 
35
- def validate_attributes
36
- redirect_uri.present?
45
+ def resource_owner
46
+ if Doorkeeper.config.polymorphic_resource_owner?
47
+ grant.resource_owner
48
+ else
49
+ grant.resource_owner_id
50
+ end
51
+ end
52
+
53
+ def pkce_supported?
54
+ Doorkeeper.config.access_grant_model.pkce_supported?
55
+ end
56
+
57
+ def validate_params
58
+ @missing_param = if grant&.uses_pkce? && code_verifier.blank?
59
+ :code_verifier
60
+ elsif redirect_uri.blank?
61
+ :redirect_uri
62
+ end
63
+
64
+ @missing_param.nil?
37
65
  end
38
66
 
39
67
  def validate_client
40
- !!client
68
+ client.present?
41
69
  end
42
70
 
43
71
  def validate_grant
44
72
  return false unless grant && grant.application_id == client.id
73
+
45
74
  grant.accessible?
46
75
  end
47
76
 
48
77
  def validate_redirect_uri
49
78
  Helpers::URIChecker.valid_for_authorization?(
50
79
  redirect_uri,
51
- grant.redirect_uri
80
+ grant.redirect_uri,
52
81
  )
53
82
  end
83
+
84
+ # if either side (server or client) request PKCE, check the verifier
85
+ # against the DB - if PKCE is supported
86
+ def validate_code_verifier
87
+ return true unless pkce_supported?
88
+ return grant.code_challenge.blank? if code_verifier.blank?
89
+
90
+ if grant.code_challenge_method == "S256"
91
+ grant.code_challenge == generate_code_challenge(code_verifier)
92
+ elsif grant.code_challenge_method == "plain"
93
+ grant.code_challenge == code_verifier
94
+ else
95
+ false
96
+ end
97
+ end
98
+
99
+ def generate_code_challenge(code_verifier)
100
+ server_config.access_grant_model.generate_code_challenge(code_verifier)
101
+ end
54
102
  end
55
103
  end
56
104
  end
@@ -1,54 +1,65 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class BaseRequest
4
6
  include Validations
5
7
 
6
- def authorize
7
- validate
8
+ attr_reader :grant_type, :server
8
9
 
10
+ delegate :default_scopes, to: :server
11
+
12
+ def authorize
9
13
  if valid?
10
14
  before_successful_response
11
15
  @response = TokenResponse.new(access_token)
12
16
  after_successful_response
13
17
  @response
18
+ elsif error == :invalid_request
19
+ @response = InvalidRequestResponse.from_request(self)
14
20
  else
15
21
  @response = ErrorResponse.from_request(self)
16
22
  end
17
23
  end
18
24
 
19
25
  def scopes
20
- @scopes ||= if @original_scopes.present?
21
- OAuth::Scopes.from_string(@original_scopes)
22
- else
23
- default_scopes
24
- end
26
+ @scopes ||= build_scopes
25
27
  end
26
28
 
27
- def default_scopes
28
- server.default_scopes
29
+ def find_or_create_access_token(client, resource_owner, scopes, server)
30
+ context = Authorization::Token.build_context(client, grant_type, scopes, resource_owner)
31
+ @access_token = server_config.access_token_model.find_or_create_for(
32
+ application: client,
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),
37
+ )
29
38
  end
30
39
 
31
- def valid?
32
- error.nil?
40
+ def before_successful_response
41
+ server_config.before_successful_strategy_response.call(self)
33
42
  end
34
43
 
35
- def find_or_create_access_token(client, resource_owner_id, scopes, server)
36
- @access_token = AccessToken.find_or_create_for(
37
- client,
38
- resource_owner_id,
39
- scopes,
40
- Authorization::Token.access_token_expires_in(server, client),
41
- server.refresh_token_enabled?
42
- )
44
+ def after_successful_response
45
+ server_config.after_successful_strategy_response.call(self, @response)
43
46
  end
44
47
 
45
- def before_successful_response
46
- Doorkeeper.configuration.before_successful_strategy_response.call(self)
48
+ def server_config
49
+ Doorkeeper.config
47
50
  end
48
51
 
49
- def after_successful_response
50
- Doorkeeper.configuration.after_successful_strategy_response.
51
- call(self, @response)
52
+ private
53
+
54
+ def build_scopes
55
+ if @original_scopes.present?
56
+ OAuth::Scopes.from_string(@original_scopes)
57
+ else
58
+ client_scopes = @client&.scopes
59
+ return default_scopes if client_scopes.blank?
60
+
61
+ default_scopes & client_scopes
62
+ end
52
63
  end
53
64
  end
54
65
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class BaseResponse
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class Client
4
6
  Credentials = Struct.new(:uid, :secret) do
5
7
  class << self
6
8
  def from_request(request, *credentials_methods)
7
- credentials_methods.inject(nil) do |credentials, method|
9
+ credentials_methods.inject(nil) do |_, method|
8
10
  method = self.method(method) if method.is_a?(Symbol)
9
11
  credentials = Credentials.new(*method.call(request))
10
- break credentials unless credentials.blank?
12
+ break credentials if credentials.present?
11
13
  end
12
14
  end
13
15
 
@@ -25,9 +27,7 @@ module Doorkeeper
25
27
 
26
28
  # Public clients may have their secret blank, but "credentials" are
27
29
  # still present
28
- def blank?
29
- uid.blank?
30
- end
30
+ delegate :blank?, to: :uid
31
31
  end
32
32
  end
33
33
  end
@@ -1,9 +1,9 @@
1
- require 'doorkeeper/oauth/client/credentials'
1
+ # frozen_string_literal: true
2
2
 
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
 
@@ -11,18 +11,17 @@ module Doorkeeper
11
11
  @application = application
12
12
  end
13
13
 
14
- def self.find(uid, method = Application.method(:by_uid))
15
- if (application = method.call(uid))
16
- new(application)
17
- end
14
+ def self.find(uid, method = Doorkeeper.config.application_model.method(:by_uid))
15
+ return unless (application = method.call(uid))
16
+
17
+ new(application)
18
18
  end
19
19
 
20
- def self.authenticate(credentials, method = Application.method(:by_uid_and_secret))
21
- return false if credentials.blank?
20
+ def self.authenticate(credentials, method = Doorkeeper.config.application_model.method(:by_uid_and_secret))
21
+ return if credentials.blank?
22
+ return unless (application = method.call(credentials.uid, credentials.secret))
22
23
 
23
- if (application = method.call(credentials.uid, credentials.secret))
24
- new(application)
25
- end
24
+ new(application)
26
25
  end
27
26
  end
28
27
  end
@@ -1,11 +1,54 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
- class ClientCredentialsRequest < BaseRequest
5
+ module ClientCredentials
4
6
  class Creator
5
7
  def call(client, scopes, attributes = {})
6
- AccessToken.find_or_create_for(
7
- client, nil, scopes, attributes[:expires_in],
8
- attributes[:use_refresh_token])
8
+ existing_token = nil
9
+
10
+ if lookup_existing_token?
11
+ existing_token = find_existing_token_for(client, scopes)
12
+ return existing_token if server_config.reuse_access_token && existing_token&.reusable?
13
+ end
14
+
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
23
+ end
24
+
25
+ private
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
+
41
+ def lookup_existing_token?
42
+ server_config.reuse_access_token ||
43
+ server_config.revoke_previous_client_credentials_token?
44
+ end
45
+
46
+ def find_existing_token_for(client, scopes)
47
+ server_config.access_token_model.matching_token_for(client, nil, scopes)
48
+ end
49
+
50
+ def server_config
51
+ Doorkeeper.config
9
52
  end
10
53
  end
11
54
  end