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
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  class Engine < Rails::Engine
3
5
  initializer "doorkeeper.params.filter" do |app|
4
6
  parameters = %w[client_secret code authentication_token access_token refresh_token]
5
- app.config.filter_parameters << /^(#{Regexp.union parameters})$/
7
+ app.config.filter_parameters << /^(#{Regexp.union(parameters)})$/
6
8
  end
7
9
 
8
10
  initializer "doorkeeper.routes" do
@@ -16,7 +18,11 @@ module Doorkeeper
16
18
  end
17
19
 
18
20
  if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
19
- initializer 'doorkeeper.assets.precompile' do |app|
21
+ initializer "doorkeeper.assets.precompile" do |app|
22
+ # Force users to use:
23
+ # //= link doorkeeper/admin/application.css
24
+ # in Doorkeeper 5 for Sprockets 4 instead of precompile.
25
+ # Add note to official docs & Wiki
20
26
  app.config.assets.precompile += %w[
21
27
  doorkeeper/application.css
22
28
  doorkeeper/admin/application.css
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Errors
3
5
  class DoorkeeperError < StandardError
@@ -6,18 +8,6 @@ module Doorkeeper
6
8
  end
7
9
  end
8
10
 
9
- class InvalidAuthorizationStrategy < DoorkeeperError
10
- def type
11
- :unsupported_response_type
12
- end
13
- end
14
-
15
- class InvalidTokenReuse < DoorkeeperError
16
- def type
17
- :invalid_request
18
- end
19
- end
20
-
21
11
  class InvalidGrantReuse < DoorkeeperError
22
12
  def type
23
13
  :invalid_grant
@@ -30,16 +20,35 @@ module Doorkeeper
30
20
  end
31
21
  end
32
22
 
33
- class MissingRequestStrategy < DoorkeeperError
23
+ class MissingRequiredParameter < DoorkeeperError
24
+ attr_reader :missing_param
25
+
26
+ def initialize(missing_param)
27
+ super
28
+ @missing_param = missing_param
29
+ end
30
+
34
31
  def type
35
32
  :invalid_request
36
33
  end
37
34
  end
38
35
 
39
- class UnableToGenerateToken < DoorkeeperError
40
- end
36
+ class BaseResponseError < DoorkeeperError
37
+ attr_reader :response
41
38
 
42
- class TokenGeneratorNotFound < DoorkeeperError
39
+ def initialize(response)
40
+ @response = response
41
+ end
43
42
  end
43
+
44
+ UnableToGenerateToken = Class.new(DoorkeeperError)
45
+ TokenGeneratorNotFound = Class.new(DoorkeeperError)
46
+ NoOrmCleaner = Class.new(DoorkeeperError)
47
+
48
+ InvalidToken = Class.new(BaseResponseError)
49
+ TokenExpired = Class.new(InvalidToken)
50
+ TokenRevoked = Class.new(InvalidToken)
51
+ TokenUnknown = Class.new(InvalidToken)
52
+ TokenForbidden = Class.new(InvalidToken)
44
53
  end
45
54
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module GrantFlow
5
+ class FallbackFlow < Flow
6
+ def handles_grant_type?
7
+ false
8
+ end
9
+
10
+ def handles_response_type?
11
+ false
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module GrantFlow
5
+ class Flow
6
+ attr_reader :name, :grant_type_matches, :grant_type_strategy,
7
+ :response_type_matches, :response_type_strategy,
8
+ :response_mode_matches
9
+
10
+ def initialize(name, **options)
11
+ @name = name
12
+ @grant_type_matches = options[:grant_type_matches]
13
+ @grant_type_strategy = options[:grant_type_strategy]
14
+ @response_type_matches = options[:response_type_matches]
15
+ @response_type_strategy = options[:response_type_strategy]
16
+ @response_mode_matches = options[:response_mode_matches]
17
+ end
18
+
19
+ def handles_grant_type?
20
+ grant_type_matches.present?
21
+ end
22
+
23
+ def handles_response_type?
24
+ response_type_matches.present?
25
+ end
26
+
27
+ def matches_grant_type?(value)
28
+ grant_type_matches === value
29
+ end
30
+
31
+ def matches_response_type?(value)
32
+ response_type_matches === value
33
+ end
34
+
35
+ def default_response_mode
36
+ response_mode_matches[0]
37
+ end
38
+
39
+ def matches_response_mode?(value)
40
+ response_mode_matches.include?(value)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module GrantFlow
5
+ module Registry
6
+ mattr_accessor :flows
7
+ self.flows = {}
8
+
9
+ mattr_accessor :aliases
10
+ self.aliases = {}
11
+
12
+ # Allows to register custom OAuth grant flow so that Doorkeeper
13
+ # could recognize and process it.
14
+ #
15
+ def register(name_or_flow, **options)
16
+ unless name_or_flow.is_a?(Doorkeeper::GrantFlow::Flow)
17
+ name_or_flow = Flow.new(name_or_flow, **options)
18
+ end
19
+
20
+ flow_key = name_or_flow.name.to_sym
21
+
22
+ if flows.key?(flow_key)
23
+ ::Kernel.warn <<~WARNING
24
+ [DOORKEEPER] '#{flow_key}' grant flow already registered and will be overridden
25
+ in #{caller(1..1).first}
26
+ WARNING
27
+ end
28
+
29
+ flows[flow_key] = name_or_flow
30
+ end
31
+
32
+ # Allows to register aliases that could be used in `grant_flows`
33
+ # configuration option. It is possible to have aliases like 1:1 or
34
+ # 1:N, i.e. "implicit_oidc" => ['token', 'id_token', 'id_token token'].
35
+ #
36
+ def register_alias(alias_name, **options)
37
+ aliases[alias_name.to_sym] = Array.wrap(options.fetch(:as))
38
+ end
39
+
40
+ def expand_alias(alias_name)
41
+ aliases.fetch(alias_name.to_sym, [])
42
+ end
43
+
44
+ # [NOTE]: make it to use #fetch after removing fallbacks
45
+ def get(name)
46
+ flows[name.to_sym]
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "doorkeeper/grant_flow/flow"
4
+ require "doorkeeper/grant_flow/fallback_flow"
5
+ require "doorkeeper/grant_flow/registry"
6
+
7
+ module Doorkeeper
8
+ module GrantFlow
9
+ extend Registry
10
+
11
+ register(
12
+ :implicit,
13
+ response_type_matches: "token",
14
+ response_mode_matches: %w[fragment form_post],
15
+ response_type_strategy: Doorkeeper::Request::Token,
16
+ )
17
+
18
+ register(
19
+ :authorization_code,
20
+ response_type_matches: "code",
21
+ response_mode_matches: %w[query fragment form_post],
22
+ response_type_strategy: Doorkeeper::Request::Code,
23
+ grant_type_matches: "authorization_code",
24
+ grant_type_strategy: Doorkeeper::Request::AuthorizationCode,
25
+ )
26
+
27
+ register(
28
+ :client_credentials,
29
+ grant_type_matches: "client_credentials",
30
+ grant_type_strategy: Doorkeeper::Request::ClientCredentials,
31
+ )
32
+
33
+ register(
34
+ :password,
35
+ grant_type_matches: "password",
36
+ grant_type_strategy: Doorkeeper::Request::Password,
37
+ )
38
+
39
+ register(
40
+ :refresh_token,
41
+ grant_type_matches: "refresh_token",
42
+ grant_type_strategy: Doorkeeper::Request::RefreshToken,
43
+ )
44
+ end
45
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Grape
3
5
  class AuthorizationDecorator < SimpleDelegator
@@ -7,10 +9,10 @@ module Doorkeeper
7
9
 
8
10
  def authorization
9
11
  env = __getobj__.env
10
- env['HTTP_AUTHORIZATION'] ||
11
- env['X-HTTP_AUTHORIZATION'] ||
12
- env['X_HTTP_AUTHORIZATION'] ||
13
- env['REDIRECT_X_HTTP_AUTHORIZATION']
12
+ env["HTTP_AUTHORIZATION"] ||
13
+ env["X-HTTP_AUTHORIZATION"] ||
14
+ env["X_HTTP_AUTHORIZATION"] ||
15
+ env["REDIRECT_X_HTTP_AUTHORIZATION"]
14
16
  end
15
17
  end
16
18
  end
@@ -1,7 +1,11 @@
1
- require 'doorkeeper/grape/authorization_decorator'
1
+ # frozen_string_literal: true
2
+
3
+ require "doorkeeper/grape/authorization_decorator"
2
4
 
3
5
  module Doorkeeper
4
6
  module Grape
7
+ # Doorkeeper helpers for Grape applications.
8
+ # Provides helpers for endpoints authorization based on defined set of scopes.
5
9
  module Helpers
6
10
  # These helpers are for grape >= 0.10
7
11
  extend ::Grape::API::Helpers
@@ -9,10 +13,12 @@ module Doorkeeper
9
13
 
10
14
  # endpoint specific scopes > parameter scopes > default scopes
11
15
  def doorkeeper_authorize!(*scopes)
12
- endpoint_scopes = endpoint.route_setting(:scopes) || endpoint.options[:route_options][:scopes]
16
+ endpoint_scopes = endpoint.route_setting(:scopes) ||
17
+ endpoint.options[:route_options][:scopes]
18
+
13
19
  scopes = if endpoint_scopes
14
20
  Doorkeeper::OAuth::Scopes.from_array(endpoint_scopes)
15
- elsif scopes && !scopes.empty?
21
+ elsif scopes.present?
16
22
  Doorkeeper::OAuth::Scopes.from_array(scopes)
17
23
  end
18
24
 
@@ -27,13 +33,13 @@ module Doorkeeper
27
33
  private
28
34
 
29
35
  def endpoint
30
- env['api.endpoint']
36
+ env["api.endpoint"]
31
37
  end
32
38
 
33
39
  def doorkeeper_token
34
- @_doorkeeper_token ||= OAuth::Token.authenticate(
40
+ @doorkeeper_token ||= OAuth::Token.authenticate(
35
41
  decorated_request,
36
- *Doorkeeper.configuration.access_token_methods
42
+ *Doorkeeper.config.access_token_methods,
37
43
  )
38
44
  end
39
45
 
@@ -44,7 +50,7 @@ module Doorkeeper
44
50
  def error_status_codes
45
51
  {
46
52
  unauthorized: 401,
47
- forbidden: 403
53
+ forbidden: 403,
48
54
  }
49
55
  end
50
56
  end
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Define methods that can be called in any controller that inherits from
2
4
  # Doorkeeper::ApplicationMetalController or Doorkeeper::ApplicationController
3
5
  module Doorkeeper
4
6
  module Helpers
7
+ # Rails controller helpers.
8
+ #
5
9
  module Controller
6
10
  private
7
11
 
@@ -12,16 +16,20 @@ module Doorkeeper
12
16
 
13
17
  # :doc:
14
18
  def current_resource_owner
15
- instance_eval(&Doorkeeper.configuration.authenticate_resource_owner)
19
+ return @current_resource_owner if defined?(@current_resource_owner)
20
+
21
+ @current_resource_owner ||= begin
22
+ instance_eval(&Doorkeeper.config.authenticate_resource_owner)
23
+ end
16
24
  end
17
25
 
18
26
  def resource_owner_from_credentials
19
- instance_eval(&Doorkeeper.configuration.resource_owner_from_credentials)
27
+ instance_eval(&Doorkeeper.config.resource_owner_from_credentials)
20
28
  end
21
29
 
22
30
  # :doc:
23
31
  def authenticate_admin!
24
- instance_eval(&Doorkeeper.configuration.authenticate_admin)
32
+ instance_eval(&Doorkeeper.config.authenticate_admin)
25
33
  end
26
34
 
27
35
  def server
@@ -30,26 +38,51 @@ module Doorkeeper
30
38
 
31
39
  # :doc:
32
40
  def doorkeeper_token
33
- @token ||= OAuth::Token.authenticate request, *config_methods
41
+ return @doorkeeper_token if defined?(@doorkeeper_token)
42
+
43
+ @doorkeeper_token ||= OAuth::Token.authenticate(request, *config_methods)
34
44
  end
35
45
 
36
46
  def config_methods
37
- @methods ||= Doorkeeper.configuration.access_token_methods
47
+ @config_methods ||= Doorkeeper.config.access_token_methods
38
48
  end
39
49
 
40
50
  def get_error_response_from_exception(exception)
41
- OAuth::ErrorResponse.new name: exception.type, state: params[:state]
51
+ if exception.respond_to?(:response)
52
+ exception.response
53
+ elsif exception.type == :invalid_request
54
+ OAuth::InvalidRequestResponse.new(
55
+ name: exception.type,
56
+ state: params[:state],
57
+ missing_param: exception.missing_param,
58
+ )
59
+ else
60
+ OAuth::ErrorResponse.new(name: exception.type, state: params[:state])
61
+ end
42
62
  end
43
63
 
44
64
  def handle_token_exception(exception)
45
- error = get_error_response_from_exception exception
46
- headers.merge! error.headers
65
+ error = get_error_response_from_exception(exception)
66
+ headers.merge!(error.headers)
47
67
  self.response_body = error.body.to_json
48
- self.status = error.status
68
+ self.status = error.status
49
69
  end
50
70
 
51
71
  def skip_authorization?
52
- !!instance_exec([@server.current_resource_owner, @pre_auth.client], &Doorkeeper.configuration.skip_authorization)
72
+ !!instance_exec(
73
+ [server.current_resource_owner, @pre_auth.client],
74
+ &Doorkeeper.config.skip_authorization
75
+ )
76
+ end
77
+
78
+ def enforce_content_type
79
+ if (request.put? || request.post? || request.patch?) && !x_www_form_urlencoded?
80
+ render json: {}, status: :unsupported_media_type
81
+ end
82
+ end
83
+
84
+ def x_www_form_urlencoded?
85
+ request.content_type == "application/x-www-form-urlencoded"
53
86
  end
54
87
  end
55
88
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module AccessGrantMixin
3
5
  extend ActiveSupport::Concern
@@ -7,7 +9,14 @@ module Doorkeeper
7
9
  include Models::Revocable
8
10
  include Models::Accessible
9
11
  include Models::Orderable
12
+ include Models::SecretStorable
10
13
  include Models::Scopes
14
+ include Models::ResourceOwnerable
15
+
16
+ # Never uses PKCE if PKCE migrations were not generated
17
+ def uses_pkce?
18
+ self.class.pkce_supported? && code_challenge.present?
19
+ end
11
20
 
12
21
  module ClassMethods
13
22
  # Searches for Doorkeeper::AccessGrant record with the
@@ -15,11 +24,96 @@ module Doorkeeper
15
24
  #
16
25
  # @param token [#to_s] token value (any object that responds to `#to_s`)
17
26
  #
18
- # @return [Doorkeeper::AccessGrant, nil] AccessGrant object or nil
19
- # if there is no record with such token
27
+ # @return [Doorkeeper::AccessGrant, nil]
28
+ # AccessGrant object or nil if there is no record with such token
20
29
  #
21
30
  def by_token(token)
22
- find_by(token: token.to_s)
31
+ find_by_plaintext_token(:token, token)
32
+ end
33
+
34
+ # Revokes AccessGrant records that have not been revoked and associated
35
+ # with the specific Application and Resource Owner.
36
+ #
37
+ # @param application_id [Integer]
38
+ # ID of the Application
39
+ # @param resource_owner [ActiveRecord::Base, Integer]
40
+ # instance of the Resource Owner model or it's ID
41
+ #
42
+ def revoke_all_for(application_id, resource_owner, clock = Time)
43
+ by_resource_owner(resource_owner)
44
+ .where(
45
+ application_id: application_id,
46
+ revoked_at: nil,
47
+ )
48
+ .update_all(revoked_at: clock.now.utc)
49
+ end
50
+
51
+ # Implements PKCE code_challenge encoding without base64 padding as described in the spec.
52
+ # https://tools.ietf.org/html/rfc7636#appendix-A
53
+ # Appendix A. Notes on Implementing Base64url Encoding without Padding
54
+ #
55
+ # This appendix describes how to implement a base64url-encoding
56
+ # function without padding, based upon the standard base64-encoding
57
+ # function that uses padding.
58
+ #
59
+ # To be concrete, example C# code implementing these functions is shown
60
+ # below. Similar code could be used in other languages.
61
+ #
62
+ # static string base64urlencode(byte [] arg)
63
+ # {
64
+ # string s = Convert.ToBase64String(arg); // Regular base64 encoder
65
+ # s = s.Split('=')[0]; // Remove any trailing '='s
66
+ # s = s.Replace('+', '-'); // 62nd char of encoding
67
+ # s = s.Replace('/', '_'); // 63rd char of encoding
68
+ # return s;
69
+ # }
70
+ #
71
+ # An example correspondence between unencoded and encoded values
72
+ # follows. The octet sequence below encodes into the string below,
73
+ # which when decoded, reproduces the octet sequence.
74
+ #
75
+ # 3 236 255 224 193
76
+ #
77
+ # A-z_4ME
78
+ #
79
+ # https://ruby-doc.org/stdlib-2.1.3/libdoc/base64/rdoc/Base64.html#method-i-urlsafe_encode64
80
+ #
81
+ # urlsafe_encode64(bin)
82
+ # Returns the Base64-encoded version of bin. This method complies with
83
+ # "Base 64 Encoding with URL and Filename Safe Alphabet" in RFC 4648.
84
+ # The alphabet uses '-' instead of '+' and '_' instead of '/'.
85
+
86
+ # @param code_verifier [#to_s] a one time use value (any object that responds to `#to_s`)
87
+ #
88
+ # @return [#to_s] An encoded code challenge based on the provided verifier
89
+ # suitable for PKCE validation
90
+ #
91
+ def generate_code_challenge(code_verifier)
92
+ Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier), padding: false)
93
+ end
94
+
95
+ def pkce_supported?
96
+ column_names.include?("code_challenge")
97
+ end
98
+
99
+ ##
100
+ # Determines the secret storing transformer
101
+ # Unless configured otherwise, uses the plain secret strategy
102
+ #
103
+ # @return [Doorkeeper::SecretStoring::Base]
104
+ #
105
+ def secret_strategy
106
+ ::Doorkeeper.config.token_secret_strategy
107
+ end
108
+
109
+ ##
110
+ # Determine the fallback storing strategy
111
+ # Unless configured, there will be no fallback
112
+ #
113
+ # @return [Doorkeeper::SecretStoring::Base]
114
+ #
115
+ def fallback_secret_strategy
116
+ ::Doorkeeper.config.token_secret_fallback_strategy
23
117
  end
24
118
  end
25
119
  end