doorkeeper 4.2.6 → 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 (274) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1049 -0
  3. data/README.md +110 -353
  4. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  5. data/app/controllers/doorkeeper/application_controller.rb +6 -7
  6. data/app/controllers/doorkeeper/application_metal_controller.rb +7 -11
  7. data/app/controllers/doorkeeper/applications_controller.rb +65 -16
  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 +115 -38
  12. data/app/helpers/doorkeeper/dashboard_helper.rb +10 -6
  13. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  14. data/app/views/doorkeeper/applications/_form.html.erb +33 -21
  15. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  16. data/app/views/doorkeeper/applications/index.html.erb +18 -6
  17. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  18. data/app/views/doorkeeper/applications/show.html.erb +40 -16
  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/doorkeeper/authorized_applications/index.html.erb +0 -1
  23. data/app/views/layouts/doorkeeper/admin.html.erb +16 -14
  24. data/config/locales/en.yml +34 -7
  25. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  26. data/lib/doorkeeper/config/option.rb +82 -0
  27. data/lib/doorkeeper/config/validations.rb +53 -0
  28. data/lib/doorkeeper/config.rb +514 -167
  29. data/lib/doorkeeper/engine.rb +11 -5
  30. data/lib/doorkeeper/errors.rb +25 -16
  31. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  32. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  33. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  34. data/lib/doorkeeper/grant_flow.rb +45 -0
  35. data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
  36. data/lib/doorkeeper/grape/helpers.rb +23 -12
  37. data/lib/doorkeeper/helpers/controller.rb +51 -14
  38. data/lib/doorkeeper/models/access_grant_mixin.rb +94 -27
  39. data/lib/doorkeeper/models/access_token_mixin.rb +284 -96
  40. data/lib/doorkeeper/models/application_mixin.rb +58 -27
  41. data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
  42. data/lib/doorkeeper/models/concerns/expirable.rb +12 -6
  43. data/lib/doorkeeper/models/concerns/orderable.rb +15 -0
  44. data/lib/doorkeeper/models/concerns/ownership.rb +4 -7
  45. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  46. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  47. data/lib/doorkeeper/models/concerns/revocable.rb +3 -27
  48. data/lib/doorkeeper/models/concerns/scopes.rb +12 -2
  49. data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
  50. data/lib/doorkeeper/oauth/authorization/code.rb +48 -12
  51. data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  52. data/lib/doorkeeper/oauth/authorization/token.rb +66 -28
  53. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +7 -5
  54. data/lib/doorkeeper/oauth/authorization_code_request.rb +63 -10
  55. data/lib/doorkeeper/oauth/base_request.rb +35 -19
  56. data/lib/doorkeeper/oauth/base_response.rb +2 -0
  57. data/lib/doorkeeper/oauth/client/credentials.rb +9 -7
  58. data/lib/doorkeeper/oauth/client.rb +10 -11
  59. data/lib/doorkeeper/oauth/client_credentials/creator.rb +47 -4
  60. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +16 -9
  61. data/lib/doorkeeper/oauth/client_credentials/validator.rb +56 -0
  62. data/lib/doorkeeper/oauth/client_credentials_request.rb +10 -11
  63. data/lib/doorkeeper/oauth/code_request.rb +8 -12
  64. data/lib/doorkeeper/oauth/code_response.rb +27 -15
  65. data/lib/doorkeeper/oauth/error.rb +5 -3
  66. data/lib/doorkeeper/oauth/error_response.rb +35 -15
  67. data/lib/doorkeeper/oauth/forbidden_token_response.rb +11 -3
  68. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -18
  69. data/lib/doorkeeper/oauth/helpers/unique_token.rb +20 -3
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +53 -3
  71. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  72. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  73. data/lib/doorkeeper/oauth/invalid_token_response.rb +29 -5
  74. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  75. data/lib/doorkeeper/oauth/password_access_token_request.rb +44 -10
  76. data/lib/doorkeeper/oauth/pre_authorization.rb +135 -26
  77. data/lib/doorkeeper/oauth/refresh_token_request.rb +60 -31
  78. data/lib/doorkeeper/oauth/scopes.rb +26 -12
  79. data/lib/doorkeeper/oauth/token.rb +13 -9
  80. data/lib/doorkeeper/oauth/token_introspection.rb +202 -0
  81. data/lib/doorkeeper/oauth/token_request.rb +8 -20
  82. data/lib/doorkeeper/oauth/token_response.rb +14 -10
  83. data/lib/doorkeeper/oauth.rb +13 -0
  84. data/lib/doorkeeper/orm/active_record/access_grant.rb +6 -4
  85. data/lib/doorkeeper/orm/active_record/access_token.rb +5 -42
  86. data/lib/doorkeeper/orm/active_record/application.rb +6 -20
  87. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +69 -0
  88. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +60 -0
  89. data/lib/doorkeeper/orm/active_record/mixins/application.rb +199 -0
  90. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  91. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +33 -0
  92. data/lib/doorkeeper/orm/active_record.rb +37 -8
  93. data/lib/doorkeeper/rails/helpers.rb +14 -13
  94. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  95. data/lib/doorkeeper/rails/routes/mapper.rb +4 -2
  96. data/lib/doorkeeper/rails/routes/mapping.rb +9 -7
  97. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  98. data/lib/doorkeeper/rails/routes.rb +41 -28
  99. data/lib/doorkeeper/rake/db.rake +40 -0
  100. data/lib/doorkeeper/rake/setup.rake +11 -0
  101. data/lib/doorkeeper/rake.rb +14 -0
  102. data/lib/doorkeeper/request/authorization_code.rb +6 -4
  103. data/lib/doorkeeper/request/client_credentials.rb +3 -3
  104. data/lib/doorkeeper/request/code.rb +1 -1
  105. data/lib/doorkeeper/request/password.rb +5 -14
  106. data/lib/doorkeeper/request/refresh_token.rb +6 -5
  107. data/lib/doorkeeper/request/strategy.rb +4 -2
  108. data/lib/doorkeeper/request/token.rb +1 -1
  109. data/lib/doorkeeper/request.rb +62 -29
  110. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  111. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  112. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  113. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  114. data/lib/doorkeeper/server.rb +9 -11
  115. data/lib/doorkeeper/stale_records_cleaner.rb +24 -0
  116. data/lib/doorkeeper/validations.rb +5 -2
  117. data/lib/doorkeeper/version.rb +12 -1
  118. data/lib/doorkeeper.rb +111 -62
  119. data/lib/generators/doorkeeper/application_owner_generator.rb +28 -13
  120. data/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
  121. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  122. data/lib/generators/doorkeeper/install_generator.rb +19 -9
  123. data/lib/generators/doorkeeper/migration_generator.rb +27 -10
  124. data/lib/generators/doorkeeper/pkce_generator.rb +33 -0
  125. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -19
  126. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  127. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +9 -0
  128. data/{spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb → lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb} +3 -1
  129. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
  130. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  131. data/lib/generators/doorkeeper/templates/initializer.rb +412 -33
  132. data/lib/generators/doorkeeper/templates/migration.rb.erb +88 -0
  133. data/lib/generators/doorkeeper/views_generator.rb +8 -4
  134. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  135. metadata +114 -276
  136. data/.coveralls.yml +0 -1
  137. data/.gitignore +0 -19
  138. data/.hound.yml +0 -13
  139. data/.rspec +0 -1
  140. data/.travis.yml +0 -26
  141. data/Appraisals +0 -14
  142. data/CONTRIBUTING.md +0 -47
  143. data/Gemfile +0 -10
  144. data/NEWS.md +0 -606
  145. data/RELEASING.md +0 -10
  146. data/Rakefile +0 -20
  147. data/app/validators/redirect_uri_validator.rb +0 -34
  148. data/doorkeeper.gemspec +0 -29
  149. data/gemfiles/rails_4_2.gemfile +0 -11
  150. data/gemfiles/rails_5_0.gemfile +0 -12
  151. data/gemfiles/rails_5_1.gemfile +0 -13
  152. data/lib/doorkeeper/oauth/client_credentials/validation.rb +0 -45
  153. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +0 -7
  154. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb +0 -11
  155. data/lib/generators/doorkeeper/templates/migration.rb +0 -68
  156. data/spec/controllers/application_metal_controller.rb +0 -10
  157. data/spec/controllers/applications_controller_spec.rb +0 -58
  158. data/spec/controllers/authorizations_controller_spec.rb +0 -218
  159. data/spec/controllers/protected_resources_controller_spec.rb +0 -300
  160. data/spec/controllers/token_info_controller_spec.rb +0 -52
  161. data/spec/controllers/tokens_controller_spec.rb +0 -88
  162. data/spec/dummy/Rakefile +0 -7
  163. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  164. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -7
  165. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -12
  166. data/spec/dummy/app/controllers/home_controller.rb +0 -17
  167. data/spec/dummy/app/controllers/metal_controller.rb +0 -11
  168. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -11
  169. data/spec/dummy/app/helpers/application_helper.rb +0 -5
  170. data/spec/dummy/app/models/user.rb +0 -5
  171. data/spec/dummy/app/views/home/index.html.erb +0 -0
  172. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  173. data/spec/dummy/config/application.rb +0 -23
  174. data/spec/dummy/config/boot.rb +0 -9
  175. data/spec/dummy/config/database.yml +0 -15
  176. data/spec/dummy/config/environment.rb +0 -5
  177. data/spec/dummy/config/environments/development.rb +0 -29
  178. data/spec/dummy/config/environments/production.rb +0 -62
  179. data/spec/dummy/config/environments/test.rb +0 -44
  180. data/spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb +0 -6
  181. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  182. data/spec/dummy/config/initializers/doorkeeper.rb +0 -96
  183. data/spec/dummy/config/initializers/secret_token.rb +0 -9
  184. data/spec/dummy/config/initializers/session_store.rb +0 -8
  185. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  186. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  187. data/spec/dummy/config/routes.rb +0 -52
  188. data/spec/dummy/config.ru +0 -4
  189. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -9
  190. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -5
  191. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -60
  192. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -7
  193. data/spec/dummy/db/schema.rb +0 -67
  194. data/spec/dummy/public/404.html +0 -26
  195. data/spec/dummy/public/422.html +0 -26
  196. data/spec/dummy/public/500.html +0 -26
  197. data/spec/dummy/public/favicon.ico +0 -0
  198. data/spec/dummy/script/rails +0 -6
  199. data/spec/factories.rb +0 -28
  200. data/spec/generators/application_owner_generator_spec.rb +0 -22
  201. data/spec/generators/install_generator_spec.rb +0 -31
  202. data/spec/generators/migration_generator_spec.rb +0 -20
  203. data/spec/generators/templates/routes.rb +0 -3
  204. data/spec/generators/views_generator_spec.rb +0 -27
  205. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -24
  206. data/spec/lib/config_spec.rb +0 -334
  207. data/spec/lib/doorkeeper_spec.rb +0 -150
  208. data/spec/lib/models/expirable_spec.rb +0 -50
  209. data/spec/lib/models/revocable_spec.rb +0 -59
  210. data/spec/lib/models/scopes_spec.rb +0 -43
  211. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -41
  212. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -80
  213. data/spec/lib/oauth/base_request_spec.rb +0 -160
  214. data/spec/lib/oauth/base_response_spec.rb +0 -45
  215. data/spec/lib/oauth/client/credentials_spec.rb +0 -88
  216. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -44
  217. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -86
  218. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -54
  219. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  220. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -104
  221. data/spec/lib/oauth/client_spec.rb +0 -39
  222. data/spec/lib/oauth/code_request_spec.rb +0 -45
  223. data/spec/lib/oauth/code_response_spec.rb +0 -34
  224. data/spec/lib/oauth/error_response_spec.rb +0 -61
  225. data/spec/lib/oauth/error_spec.rb +0 -23
  226. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -23
  227. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -64
  228. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -20
  229. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -104
  230. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -56
  231. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -90
  232. data/spec/lib/oauth/pre_authorization_spec.rb +0 -155
  233. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -154
  234. data/spec/lib/oauth/scopes_spec.rb +0 -122
  235. data/spec/lib/oauth/token_request_spec.rb +0 -98
  236. data/spec/lib/oauth/token_response_spec.rb +0 -85
  237. data/spec/lib/oauth/token_spec.rb +0 -116
  238. data/spec/lib/request/strategy_spec.rb +0 -53
  239. data/spec/lib/server_spec.rb +0 -49
  240. data/spec/models/doorkeeper/access_grant_spec.rb +0 -36
  241. data/spec/models/doorkeeper/access_token_spec.rb +0 -394
  242. data/spec/models/doorkeeper/application_spec.rb +0 -179
  243. data/spec/requests/applications/applications_request_spec.rb +0 -94
  244. data/spec/requests/applications/authorized_applications_spec.rb +0 -30
  245. data/spec/requests/endpoints/authorization_spec.rb +0 -71
  246. data/spec/requests/endpoints/token_spec.rb +0 -64
  247. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -76
  248. data/spec/requests/flows/authorization_code_spec.rb +0 -148
  249. data/spec/requests/flows/client_credentials_spec.rb +0 -58
  250. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -32
  251. data/spec/requests/flows/implicit_grant_spec.rb +0 -61
  252. data/spec/requests/flows/password_spec.rb +0 -115
  253. data/spec/requests/flows/refresh_token_spec.rb +0 -174
  254. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  255. data/spec/requests/flows/skip_authorization_spec.rb +0 -59
  256. data/spec/requests/protected_resources/metal_spec.rb +0 -14
  257. data/spec/requests/protected_resources/private_api_spec.rb +0 -81
  258. data/spec/routing/custom_controller_routes_spec.rb +0 -71
  259. data/spec/routing/default_routes_spec.rb +0 -35
  260. data/spec/routing/scoped_routes_spec.rb +0 -31
  261. data/spec/spec_helper.rb +0 -4
  262. data/spec/spec_helper_integration.rb +0 -63
  263. data/spec/support/dependencies/factory_girl.rb +0 -2
  264. data/spec/support/helpers/access_token_request_helper.rb +0 -11
  265. data/spec/support/helpers/authorization_request_helper.rb +0 -41
  266. data/spec/support/helpers/config_helper.rb +0 -9
  267. data/spec/support/helpers/model_helper.rb +0 -67
  268. data/spec/support/helpers/request_spec_helper.rb +0 -84
  269. data/spec/support/helpers/url_helper.rb +0 -55
  270. data/spec/support/http_method_shim.rb +0 -38
  271. data/spec/support/orm/active_record.rb +0 -3
  272. data/spec/support/shared/controllers_shared_context.rb +0 -69
  273. data/spec/support/shared/models_shared_examples.rb +0 -52
  274. data/spec/validators/redirect_uri_validator_spec.rb +0 -78
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper::Orm::ActiveRecord::Mixins
4
+ module AccessGrant
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ self.table_name = compute_doorkeeper_table_name
9
+ self.strict_loading_by_default = false if respond_to?(:strict_loading_by_default)
10
+
11
+ include ::Doorkeeper::AccessGrantMixin
12
+
13
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
14
+ optional: true,
15
+ inverse_of: :access_grants
16
+
17
+ if Doorkeeper.config.polymorphic_resource_owner?
18
+ belongs_to :resource_owner, polymorphic: true, optional: false
19
+ else
20
+ validates :resource_owner_id, presence: true
21
+ end
22
+
23
+ validates :application_id,
24
+ :token,
25
+ :expires_in,
26
+ :redirect_uri,
27
+ presence: true
28
+
29
+ validates :token, uniqueness: { case_sensitive: true }
30
+
31
+ before_validation :generate_token, on: :create
32
+
33
+ # We keep a volatile copy of the raw token for initial communication
34
+ # The stored refresh_token may be mapped and not available in cleartext.
35
+ #
36
+ # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
37
+ # while hashing strategies do not, so you cannot rely on this value
38
+ # returning a present value for persisted tokens.
39
+ def plaintext_token
40
+ if secret_strategy.allows_restoring_secrets?
41
+ secret_strategy.restore_secret(self, :token)
42
+ else
43
+ @raw_token
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ # Generates token value with UniqueToken class.
50
+ #
51
+ # @return [String] token value
52
+ #
53
+ def generate_token
54
+ @raw_token = Doorkeeper::OAuth::Helpers::UniqueToken.generate
55
+ secret_strategy.store_secret(self, :token, @raw_token)
56
+ end
57
+ end
58
+
59
+ module ClassMethods
60
+ private
61
+
62
+ def compute_doorkeeper_table_name
63
+ table_name = "oauth_access_grant"
64
+ table_name = table_name.pluralize if pluralize_table_names
65
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper::Orm::ActiveRecord::Mixins
4
+ module AccessToken
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ self.table_name = compute_doorkeeper_table_name
9
+ self.strict_loading_by_default = false if respond_to?(:strict_loading_by_default)
10
+
11
+ include ::Doorkeeper::AccessTokenMixin
12
+
13
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
14
+ inverse_of: :access_tokens,
15
+ optional: true
16
+
17
+ if Doorkeeper.config.polymorphic_resource_owner?
18
+ belongs_to :resource_owner, polymorphic: true, optional: true
19
+ end
20
+
21
+ validates :token, presence: true, uniqueness: { case_sensitive: true }
22
+ validates :refresh_token, uniqueness: { case_sensitive: true }, if: :use_refresh_token?
23
+
24
+ # @attr_writer [Boolean, nil] use_refresh_token
25
+ # indicates the possibility of using refresh token
26
+ attr_writer :use_refresh_token
27
+
28
+ before_validation :generate_token, on: :create
29
+ before_validation :generate_refresh_token,
30
+ on: :create, if: :use_refresh_token?
31
+ end
32
+
33
+ module ClassMethods
34
+ # Searches for not revoked Access Tokens associated with the
35
+ # specific Resource Owner.
36
+ #
37
+ # @param resource_owner [ActiveRecord::Base]
38
+ # Resource Owner model instance
39
+ #
40
+ # @return [ActiveRecord::Relation]
41
+ # active Access Tokens for Resource Owner
42
+ #
43
+ def active_for(resource_owner)
44
+ by_resource_owner(resource_owner).where(revoked_at: nil)
45
+ end
46
+
47
+ def refresh_token_revoked_on_use?
48
+ column_names.include?("previous_refresh_token")
49
+ end
50
+
51
+ private
52
+
53
+ def compute_doorkeeper_table_name
54
+ table_name = "oauth_access_token"
55
+ table_name = table_name.pluralize if pluralize_table_names
56
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper::Orm::ActiveRecord::Mixins
4
+ module Application
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ self.table_name = compute_doorkeeper_table_name
9
+ self.strict_loading_by_default = false if respond_to?(:strict_loading_by_default)
10
+
11
+ include ::Doorkeeper::ApplicationMixin
12
+
13
+ has_many :access_grants,
14
+ foreign_key: :application_id,
15
+ dependent: :delete_all,
16
+ class_name: Doorkeeper.config.access_grant_class.to_s
17
+
18
+ has_many :access_tokens,
19
+ foreign_key: :application_id,
20
+ dependent: :delete_all,
21
+ class_name: Doorkeeper.config.access_token_class.to_s
22
+
23
+ validates :name, :secret, :uid, presence: true
24
+ validates :uid, uniqueness: { case_sensitive: true }
25
+ validates :redirect_uri, "doorkeeper/redirect_uri": true
26
+ validates :confidential, inclusion: { in: [true, false] }
27
+
28
+ validate :scopes_match_configured, if: :enforce_scopes?
29
+
30
+ before_validation :generate_uid, :generate_secret, on: :create
31
+
32
+ has_many :authorized_tokens,
33
+ -> { where(revoked_at: nil) },
34
+ foreign_key: :application_id,
35
+ class_name: Doorkeeper.config.access_token_class.to_s
36
+
37
+ has_many :authorized_applications,
38
+ through: :authorized_tokens,
39
+ source: :application
40
+
41
+ # Generates a new secret for this application, intended to be used
42
+ # for rotating the secret or in case of compromise.
43
+ #
44
+ # @return [String] new transformed secret value
45
+ #
46
+ def renew_secret
47
+ @raw_secret = Doorkeeper::OAuth::Helpers::UniqueToken.generate
48
+ secret_strategy.store_secret(self, :secret, @raw_secret)
49
+ end
50
+
51
+ # We keep a volatile copy of the raw secret for initial communication
52
+ # The stored refresh_token may be mapped and not available in cleartext.
53
+ #
54
+ # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
55
+ # while hashing strategies do not, so you cannot rely on this value
56
+ # returning a present value for persisted tokens.
57
+ def plaintext_secret
58
+ if secret_strategy.allows_restoring_secrets?
59
+ secret_strategy.restore_secret(self, :secret)
60
+ else
61
+ @raw_secret
62
+ end
63
+ end
64
+
65
+ # Represents client as set of it's attributes in JSON format.
66
+ # This is the right way how we want to override ActiveRecord #to_json.
67
+ #
68
+ # Respects privacy settings and serializes minimum set of attributes
69
+ # for public/private clients and full set for authorized owners.
70
+ #
71
+ # @return [Hash] entity attributes for JSON
72
+ #
73
+ def as_json(options = {})
74
+ # if application belongs to some owner we need to check if it's the same as
75
+ # the one passed in the options or check if we render the client as an owner
76
+ if (respond_to?(:owner) && owner && owner == options[:current_resource_owner]) ||
77
+ options[:as_owner]
78
+ # Owners can see all the client attributes, fallback to ActiveModel serialization
79
+ super
80
+ else
81
+ # if application has no owner or it's owner doesn't match one from the options
82
+ # we render only minimum set of attributes that could be exposed to a public
83
+ only = extract_serializable_attributes(options)
84
+ super(options.merge(only: only))
85
+ end
86
+ end
87
+
88
+ def authorized_for_resource_owner?(resource_owner)
89
+ Doorkeeper.configuration.authorize_resource_owner_for_client.call(self, resource_owner)
90
+ end
91
+
92
+ # We need to hook into this method to allow serializing plan-text secrets
93
+ # when secrets hashing enabled.
94
+ #
95
+ # @param key [String] attribute name
96
+ #
97
+ def read_attribute_for_serialization(key)
98
+ return super unless key.to_s == "secret"
99
+
100
+ plaintext_secret || secret
101
+ end
102
+
103
+ private
104
+
105
+ def generate_uid
106
+ self.uid = Doorkeeper::OAuth::Helpers::UniqueToken.generate if uid.blank?
107
+ end
108
+
109
+ def generate_secret
110
+ return if secret.present?
111
+
112
+ renew_secret
113
+ end
114
+
115
+ def scopes_match_configured
116
+ if scopes.present? && !Doorkeeper::OAuth::Helpers::ScopeChecker.valid?(
117
+ scope_str: scopes.to_s,
118
+ server_scopes: Doorkeeper.config.scopes,
119
+ )
120
+ errors.add(:scopes, :not_match_configured)
121
+ end
122
+ end
123
+
124
+ def enforce_scopes?
125
+ Doorkeeper.config.enforce_configured_scopes?
126
+ end
127
+
128
+ # Helper method to extract collection of serializable attribute names
129
+ # considering serialization options (like `only`, `except` and so on).
130
+ #
131
+ # @param options [Hash] serialization options
132
+ #
133
+ # @return [Array<String>]
134
+ # collection of attributes to be serialized using #as_json
135
+ #
136
+ def extract_serializable_attributes(options = {})
137
+ opts = options.try(:dup) || {}
138
+ only = Array.wrap(opts[:only]).map(&:to_s)
139
+
140
+ only = if only.blank?
141
+ client_serializable_attributes
142
+ else
143
+ only & client_serializable_attributes
144
+ end
145
+
146
+ only -= Array.wrap(opts[:except]).map(&:to_s) if opts.key?(:except)
147
+ only.uniq
148
+ end
149
+
150
+ # Collection of attributes that could be serialized for public.
151
+ # Override this method if you need additional attributes to be serialized.
152
+ #
153
+ # @return [Array<String>] collection of serializable attributes
154
+ #
155
+ # NOTE: `serializable_attributes` method already taken by Rails >= 6
156
+ #
157
+ def client_serializable_attributes
158
+ attributes = %w[id name created_at]
159
+ attributes << "uid" unless confidential?
160
+ attributes
161
+ end
162
+ end
163
+
164
+ module ClassMethods
165
+ # Returns Applications associated with active (not revoked) Access Tokens
166
+ # that are owned by the specific Resource Owner.
167
+ #
168
+ # @param resource_owner [ActiveRecord::Base]
169
+ # Resource Owner model instance
170
+ #
171
+ # @return [ActiveRecord::Relation]
172
+ # Applications authorized for the Resource Owner
173
+ #
174
+ def authorized_for(resource_owner)
175
+ resource_access_tokens = Doorkeeper.config.access_token_model.active_for(resource_owner)
176
+ where(id: resource_access_tokens.select(:application_id).distinct)
177
+ end
178
+
179
+ # Revokes AccessToken and AccessGrant records that have not been revoked and
180
+ # associated with the specific Application and Resource Owner.
181
+ #
182
+ # @param resource_owner [ActiveRecord::Base]
183
+ # instance of the Resource Owner model
184
+ #
185
+ def revoke_tokens_and_grants_for(id, resource_owner)
186
+ Doorkeeper.config.access_token_model.revoke_all_for(id, resource_owner)
187
+ Doorkeeper.config.access_grant_model.revoke_all_for(id, resource_owner)
188
+ end
189
+
190
+ private
191
+
192
+ def compute_doorkeeper_table_name
193
+ table_name = "oauth_application"
194
+ table_name = table_name.pluralize if pluralize_table_names
195
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module Doorkeeper
6
+ # ActiveModel validator for redirect URI validation in according
7
+ # to OAuth standards and Doorkeeper configuration.
8
+ class RedirectUriValidator < ActiveModel::EachValidator
9
+ def validate_each(record, attribute, value)
10
+ if value.blank?
11
+ return if Doorkeeper.config.allow_blank_redirect_uri?(record)
12
+
13
+ record.errors.add(attribute, :blank)
14
+ else
15
+ value.split.each do |val|
16
+ next if oob_redirect_uri?(val)
17
+
18
+ uri = ::URI.parse(val)
19
+ record.errors.add(attribute, :forbidden_uri) if forbidden_uri?(uri)
20
+ record.errors.add(attribute, :fragment_present) unless uri.fragment.nil?
21
+ record.errors.add(attribute, :unspecified_scheme) if unspecified_scheme?(uri)
22
+ record.errors.add(attribute, :relative_uri) if relative_uri?(uri)
23
+ record.errors.add(attribute, :secured_uri) if invalid_ssl_uri?(uri)
24
+ record.errors.add(attribute, :invalid_uri) if unspecified_host?(uri)
25
+ end
26
+ end
27
+ rescue URI::InvalidURIError
28
+ record.errors.add(attribute, :invalid_uri)
29
+ end
30
+
31
+ private
32
+
33
+ def oob_redirect_uri?(uri)
34
+ Doorkeeper::OAuth::NonStandard::IETF_WG_OAUTH2_OOB_METHODS.include?(uri)
35
+ end
36
+
37
+ def forbidden_uri?(uri)
38
+ Doorkeeper.config.forbid_redirect_uri.call(uri)
39
+ end
40
+
41
+ def unspecified_scheme?(uri)
42
+ return true if uri.opaque.present?
43
+
44
+ %w[localhost].include?(uri.try(:scheme))
45
+ end
46
+
47
+ def unspecified_host?(uri)
48
+ uri.is_a?(URI::HTTP) && uri.host.nil?
49
+ end
50
+
51
+ def relative_uri?(uri)
52
+ uri.scheme.nil? && uri.host.nil?
53
+ end
54
+
55
+ def invalid_ssl_uri?(uri)
56
+ forces_ssl = Doorkeeper.config.force_ssl_in_redirect_uri
57
+ non_https = uri.try(:scheme) == "http"
58
+
59
+ if forces_ssl.respond_to?(:call)
60
+ forces_ssl.call(uri) && non_https
61
+ else
62
+ forces_ssl && non_https
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Orm
5
+ module ActiveRecord
6
+ # Helper class to clear stale and non-active tokens and grants.
7
+ # Used by Doorkeeper Rake tasks.
8
+ #
9
+ class StaleRecordsCleaner
10
+ def initialize(base_scope)
11
+ @base_scope = base_scope
12
+ end
13
+
14
+ # Clears revoked records
15
+ def clean_revoked
16
+ table = @base_scope.arel_table
17
+
18
+ @base_scope.where.not(revoked_at: nil)
19
+ .where(table[:revoked_at].lt(Time.current))
20
+ .in_batches(&:delete_all)
21
+ end
22
+
23
+ # Clears expired records
24
+ def clean_expired(ttl)
25
+ table = @base_scope.arel_table
26
+
27
+ @base_scope.where(table[:created_at].lt(Time.current - ttl))
28
+ .in_batches(&:delete_all)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,22 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/lazy_load_hooks"
4
+
1
5
  module Doorkeeper
2
6
  module Orm
7
+ # ActiveRecord ORM for Doorkeeper entity models.
8
+ # Consists of three main OAuth entities:
9
+ # * Access Token
10
+ # * Access Grant
11
+ # * Application (client)
12
+ #
13
+ # Do a lazy loading of all the required and configured stuff.
14
+ #
3
15
  module ActiveRecord
4
16
  def self.initialize_models!
5
- require 'doorkeeper/orm/active_record/access_grant'
6
- require 'doorkeeper/orm/active_record/access_token'
7
- require 'doorkeeper/orm/active_record/application'
17
+ lazy_load do
18
+ require "doorkeeper/orm/active_record/stale_records_cleaner"
19
+ require "doorkeeper/orm/active_record/access_grant"
20
+ require "doorkeeper/orm/active_record/access_token"
21
+ require "doorkeeper/orm/active_record/application"
8
22
 
9
- if Doorkeeper.configuration.active_record_options[:establish_connection]
10
- [Doorkeeper::AccessGrant, Doorkeeper::AccessToken, Doorkeeper::Application].each do |c|
11
- c.send :establish_connection, Doorkeeper.configuration.active_record_options[:establish_connection]
23
+ if (options = Doorkeeper.config.active_record_options[:establish_connection])
24
+ Doorkeeper::Orm::ActiveRecord.models.each do |model|
25
+ model.establish_connection(options)
26
+ end
12
27
  end
13
28
  end
14
29
  end
15
30
 
16
31
  def self.initialize_application_owner!
17
- require 'doorkeeper/models/concerns/ownership'
32
+ lazy_load do
33
+ require "doorkeeper/models/concerns/ownership"
34
+
35
+ Doorkeeper.config.application_model.include(Doorkeeper::Models::Ownership)
36
+ end
37
+ end
38
+
39
+ def self.lazy_load(&block)
40
+ ActiveSupport.on_load(:active_record, {}, &block)
41
+ end
18
42
 
19
- Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
43
+ def self.models
44
+ [
45
+ Doorkeeper.config.access_grant_model,
46
+ Doorkeeper.config.access_token_model,
47
+ Doorkeeper.config.application_model,
48
+ ]
20
49
  end
21
50
  end
22
51
  end
@@ -1,36 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Rails
3
5
  module Helpers
4
6
  def doorkeeper_authorize!(*scopes)
5
- @_doorkeeper_scopes = scopes.presence || Doorkeeper.configuration.default_scopes
7
+ @_doorkeeper_scopes = scopes.presence || Doorkeeper.config.default_scopes
6
8
 
7
- unless valid_doorkeeper_token?
8
- doorkeeper_render_error
9
- end
9
+ doorkeeper_render_error unless valid_doorkeeper_token?
10
10
  end
11
11
 
12
- def doorkeeper_unauthorized_render_options(error: nil)
13
- end
12
+ def doorkeeper_unauthorized_render_options(**); end
14
13
 
15
- def doorkeeper_forbidden_render_options(error: nil)
16
- end
14
+ def doorkeeper_forbidden_render_options(**); end
17
15
 
18
16
  def valid_doorkeeper_token?
19
- doorkeeper_token && doorkeeper_token.acceptable?(@_doorkeeper_scopes)
17
+ doorkeeper_token&.acceptable?(@_doorkeeper_scopes)
20
18
  end
21
19
 
22
20
  private
23
21
 
24
22
  def doorkeeper_render_error
25
23
  error = doorkeeper_error
26
- headers.merge! error.headers.reject { |k| "Content-Type" == k }
24
+ error.raise_exception! if Doorkeeper.config.raise_on_errors?
25
+
26
+ headers.merge!(error.headers.reject { |k| k == "Content-Type" })
27
27
  doorkeeper_render_error_with(error)
28
28
  end
29
29
 
30
30
  def doorkeeper_render_error_with(error)
31
31
  options = doorkeeper_render_options(error) || {}
32
32
  status = doorkeeper_status_for_error(
33
- error, options.delete(:respond_not_found_when_forbidden))
33
+ error, options.delete(:respond_not_found_when_forbidden),
34
+ )
34
35
  if options.blank?
35
36
  head status
36
37
  else
@@ -69,9 +70,9 @@ module Doorkeeper
69
70
  end
70
71
 
71
72
  def doorkeeper_token
72
- @_doorkeeper_token ||= OAuth::Token.authenticate(
73
+ @doorkeeper_token ||= OAuth::Token.authenticate(
73
74
  request,
74
- *Doorkeeper.configuration.access_token_methods
75
+ *Doorkeeper.config.access_token_methods,
75
76
  )
76
77
  end
77
78
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Rails
5
+ # Abstract router module that implements base behavior
6
+ # for generating and mapping Rails routes.
7
+ #
8
+ # Could be reused in Doorkeeper extensions.
9
+ #
10
+ module AbstractRouter
11
+ extend ActiveSupport::Concern
12
+
13
+ attr_reader :routes
14
+
15
+ def initialize(routes, mapper = Mapper.new, &block)
16
+ @routes = routes
17
+ @mapping = mapper.map(&block)
18
+ end
19
+
20
+ def generate_routes!(**_options)
21
+ raise NotImplementedError, "must be redefined for #{self.class.name}!"
22
+ end
23
+
24
+ private
25
+
26
+ def map_route(name, method)
27
+ return if @mapping.skipped?(name)
28
+
29
+ send(method, @mapping[name])
30
+
31
+ mapping[name] = @mapping[name]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Rails
3
5
  class Routes # :nodoc:
4
6
  class Mapper
5
- def initialize
6
- @mapping = Mapping.new
7
+ def initialize(mapping = Mapping.new)
8
+ @mapping = mapping
7
9
  end
8
10
 
9
11
  def map(&block)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Rails
3
5
  class Routes # :nodoc:
@@ -6,17 +8,17 @@ module Doorkeeper
6
8
 
7
9
  def initialize
8
10
  @controllers = {
9
- authorizations: 'doorkeeper/authorizations',
10
- applications: 'doorkeeper/applications',
11
- authorized_applications: 'doorkeeper/authorized_applications',
12
- tokens: 'doorkeeper/tokens',
13
- token_info: 'doorkeeper/token_info'
11
+ authorizations: "doorkeeper/authorizations",
12
+ applications: "doorkeeper/applications",
13
+ authorized_applications: "doorkeeper/authorized_applications",
14
+ tokens: "doorkeeper/tokens",
15
+ token_info: "doorkeeper/token_info",
14
16
  }
15
17
 
16
18
  @as = {
17
19
  authorizations: :authorization,
18
20
  tokens: :token,
19
- token_info: :token_info
21
+ token_info: :token_info,
20
22
  }
21
23
 
22
24
  @skips = []
@@ -25,7 +27,7 @@ module Doorkeeper
25
27
  def [](routes)
26
28
  {
27
29
  controllers: @controllers[routes],
28
- as: @as[routes]
30
+ as: @as[routes],
29
31
  }
30
32
  end
31
33
 
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Rails
5
+ class Routes
6
+ # Thread-safe registry of any Doorkeeper additional routes.
7
+ # Used to allow implementing of Doorkeeper extensions that must
8
+ # use their own routes.
9
+ #
10
+ module Registry
11
+ ROUTES_ACCESS_LOCK = Mutex.new
12
+ ROUTES_DEFINITION_LOCK = Mutex.new
13
+
14
+ InvalidRouterClass = Class.new(StandardError)
15
+
16
+ # Collection of additional registered routes for Doorkeeper.
17
+ #
18
+ # @return [Array<Object>] set of registered routes
19
+ #
20
+ def registered_routes
21
+ ROUTES_DEFINITION_LOCK.synchronize do
22
+ @registered_routes ||= Set.new
23
+ end
24
+ end
25
+
26
+ # Registers additional routes in the Doorkeeper registry
27
+ #
28
+ # @param [Object] routes
29
+ # routes class
30
+ #
31
+ def register_routes(routes)
32
+ if !routes.is_a?(Module) || !(routes < AbstractRouter)
33
+ raise InvalidRouterClass, "routes class must include Doorkeeper::Rails::AbstractRouter"
34
+ end
35
+
36
+ ROUTES_ACCESS_LOCK.synchronize do
37
+ registered_routes << routes
38
+ end
39
+ end
40
+
41
+ alias register register_routes
42
+ end
43
+ end
44
+ end
45
+ end