doorkeeper 4.2.0 → 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 (271) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1038 -0
  3. data/README.md +110 -348
  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 -20
  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 +112 -35
  12. data/app/helpers/doorkeeper/dashboard_helper.rb +10 -6
  13. data/app/views/doorkeeper/applications/_delete_form.html.erb +4 -3
  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 +7 -1
  22. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  23. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  24. data/app/views/layouts/doorkeeper/admin.html.erb +16 -14
  25. data/config/locales/en.yml +33 -9
  26. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  27. data/lib/doorkeeper/config/option.rb +82 -0
  28. data/lib/doorkeeper/config/validations.rb +53 -0
  29. data/lib/doorkeeper/config.rb +545 -143
  30. data/lib/doorkeeper/engine.rb +11 -5
  31. data/lib/doorkeeper/errors.rb +37 -10
  32. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  33. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  34. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  35. data/lib/doorkeeper/grant_flow.rb +45 -0
  36. data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
  37. data/lib/doorkeeper/grape/helpers.rb +24 -12
  38. data/lib/doorkeeper/helpers/controller.rb +49 -27
  39. data/lib/doorkeeper/models/access_grant_mixin.rb +100 -21
  40. data/lib/doorkeeper/models/access_token_mixin.rb +379 -75
  41. data/lib/doorkeeper/models/application_mixin.rb +72 -25
  42. data/lib/doorkeeper/models/concerns/accessible.rb +6 -0
  43. data/lib/doorkeeper/models/concerns/expirable.rb +20 -6
  44. data/lib/doorkeeper/models/concerns/orderable.rb +15 -0
  45. data/lib/doorkeeper/models/concerns/ownership.rb +4 -7
  46. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  47. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  48. data/lib/doorkeeper/models/concerns/revocable.rb +12 -18
  49. data/lib/doorkeeper/models/concerns/scopes.rb +12 -2
  50. data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
  51. data/lib/doorkeeper/oauth/authorization/code.rb +48 -12
  52. data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  53. data/lib/doorkeeper/oauth/authorization/token.rb +66 -28
  54. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +22 -18
  55. data/lib/doorkeeper/oauth/authorization_code_request.rb +64 -14
  56. data/lib/doorkeeper/oauth/base_request.rb +66 -0
  57. data/lib/doorkeeper/oauth/base_response.rb +31 -0
  58. data/lib/doorkeeper/oauth/client/credentials.rb +23 -10
  59. data/lib/doorkeeper/oauth/client.rb +10 -12
  60. data/lib/doorkeeper/oauth/client_credentials/creator.rb +47 -4
  61. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +16 -9
  62. data/lib/doorkeeper/oauth/client_credentials/validator.rb +56 -0
  63. data/lib/doorkeeper/oauth/client_credentials_request.rb +11 -15
  64. data/lib/doorkeeper/oauth/code_request.rb +8 -12
  65. data/lib/doorkeeper/oauth/code_response.rb +28 -15
  66. data/lib/doorkeeper/oauth/error.rb +5 -3
  67. data/lib/doorkeeper/oauth/error_response.rb +41 -20
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +10 -3
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -18
  70. data/lib/doorkeeper/oauth/helpers/unique_token.rb +20 -3
  71. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +53 -3
  72. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  73. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  74. data/lib/doorkeeper/oauth/invalid_token_response.rb +31 -5
  75. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  76. data/lib/doorkeeper/oauth/password_access_token_request.rb +45 -13
  77. data/lib/doorkeeper/oauth/pre_authorization.rb +135 -26
  78. data/lib/doorkeeper/oauth/refresh_token_request.rb +61 -36
  79. data/lib/doorkeeper/oauth/scopes.rb +26 -12
  80. data/lib/doorkeeper/oauth/token.rb +25 -23
  81. data/lib/doorkeeper/oauth/token_introspection.rb +202 -0
  82. data/lib/doorkeeper/oauth/token_request.rb +8 -21
  83. data/lib/doorkeeper/oauth/token_response.rb +14 -10
  84. data/lib/doorkeeper/oauth.rb +13 -0
  85. data/lib/doorkeeper/orm/active_record/access_grant.rb +6 -4
  86. data/lib/doorkeeper/orm/active_record/access_token.rb +5 -25
  87. data/lib/doorkeeper/orm/active_record/application.rb +6 -15
  88. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +68 -0
  89. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +59 -0
  90. data/lib/doorkeeper/orm/active_record/mixins/application.rb +198 -0
  91. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  92. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +33 -0
  93. data/lib/doorkeeper/orm/active_record.rb +37 -8
  94. data/lib/doorkeeper/rails/helpers.rb +14 -15
  95. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  96. data/lib/doorkeeper/rails/routes/mapper.rb +3 -1
  97. data/lib/doorkeeper/rails/routes/mapping.rb +10 -8
  98. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  99. data/lib/doorkeeper/rails/routes.rb +42 -30
  100. data/lib/doorkeeper/rake/db.rake +40 -0
  101. data/lib/doorkeeper/rake/setup.rake +11 -0
  102. data/lib/doorkeeper/rake.rb +14 -0
  103. data/lib/doorkeeper/request/authorization_code.rb +12 -4
  104. data/lib/doorkeeper/request/client_credentials.rb +3 -3
  105. data/lib/doorkeeper/request/code.rb +1 -1
  106. data/lib/doorkeeper/request/password.rb +5 -14
  107. data/lib/doorkeeper/request/refresh_token.rb +6 -5
  108. data/lib/doorkeeper/request/strategy.rb +4 -2
  109. data/lib/doorkeeper/request/token.rb +1 -1
  110. data/lib/doorkeeper/request.rb +62 -29
  111. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  112. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  113. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  114. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  115. data/lib/doorkeeper/server.rb +9 -19
  116. data/lib/doorkeeper/stale_records_cleaner.rb +24 -0
  117. data/lib/doorkeeper/validations.rb +5 -2
  118. data/lib/doorkeeper/version.rb +12 -1
  119. data/lib/doorkeeper.rb +111 -56
  120. data/lib/generators/doorkeeper/application_owner_generator.rb +28 -13
  121. data/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
  122. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  123. data/lib/generators/doorkeeper/install_generator.rb +19 -9
  124. data/lib/generators/doorkeeper/migration_generator.rb +27 -10
  125. data/lib/generators/doorkeeper/pkce_generator.rb +33 -0
  126. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -19
  127. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  128. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +9 -0
  129. data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +3 -1
  130. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
  131. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  132. data/lib/generators/doorkeeper/templates/initializer.rb +410 -31
  133. data/lib/generators/doorkeeper/templates/migration.rb.erb +88 -0
  134. data/lib/generators/doorkeeper/views_generator.rb +8 -4
  135. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  136. metadata +132 -286
  137. data/.gitignore +0 -14
  138. data/.hound.yml +0 -13
  139. data/.rspec +0 -1
  140. data/.travis.yml +0 -20
  141. data/CONTRIBUTING.md +0 -47
  142. data/Gemfile +0 -14
  143. data/NEWS.md +0 -593
  144. data/RELEASING.md +0 -17
  145. data/Rakefile +0 -20
  146. data/app/validators/redirect_uri_validator.rb +0 -34
  147. data/doorkeeper.gemspec +0 -28
  148. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  149. data/lib/doorkeeper/oauth/client_credentials/validation.rb +0 -45
  150. data/lib/doorkeeper/oauth/request_concern.rb +0 -48
  151. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +0 -7
  152. data/lib/generators/doorkeeper/templates/migration.rb +0 -68
  153. data/spec/controllers/application_metal_controller.rb +0 -10
  154. data/spec/controllers/applications_controller_spec.rb +0 -58
  155. data/spec/controllers/authorizations_controller_spec.rb +0 -189
  156. data/spec/controllers/protected_resources_controller_spec.rb +0 -300
  157. data/spec/controllers/token_info_controller_spec.rb +0 -52
  158. data/spec/controllers/tokens_controller_spec.rb +0 -88
  159. data/spec/dummy/Rakefile +0 -7
  160. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  161. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -7
  162. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -12
  163. data/spec/dummy/app/controllers/home_controller.rb +0 -17
  164. data/spec/dummy/app/controllers/metal_controller.rb +0 -11
  165. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -11
  166. data/spec/dummy/app/helpers/application_helper.rb +0 -5
  167. data/spec/dummy/app/models/user.rb +0 -5
  168. data/spec/dummy/app/views/home/index.html.erb +0 -0
  169. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  170. data/spec/dummy/config/application.rb +0 -23
  171. data/spec/dummy/config/boot.rb +0 -9
  172. data/spec/dummy/config/database.yml +0 -15
  173. data/spec/dummy/config/environment.rb +0 -5
  174. data/spec/dummy/config/environments/development.rb +0 -29
  175. data/spec/dummy/config/environments/production.rb +0 -62
  176. data/spec/dummy/config/environments/test.rb +0 -44
  177. data/spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb +0 -6
  178. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  179. data/spec/dummy/config/initializers/doorkeeper.rb +0 -96
  180. data/spec/dummy/config/initializers/secret_token.rb +0 -9
  181. data/spec/dummy/config/initializers/session_store.rb +0 -8
  182. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  183. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  184. data/spec/dummy/config/routes.rb +0 -52
  185. data/spec/dummy/config.ru +0 -4
  186. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -9
  187. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -5
  188. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -60
  189. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -7
  190. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -11
  191. data/spec/dummy/db/schema.rb +0 -67
  192. data/spec/dummy/public/404.html +0 -26
  193. data/spec/dummy/public/422.html +0 -26
  194. data/spec/dummy/public/500.html +0 -26
  195. data/spec/dummy/public/favicon.ico +0 -0
  196. data/spec/dummy/script/rails +0 -6
  197. data/spec/factories.rb +0 -28
  198. data/spec/generators/application_owner_generator_spec.rb +0 -22
  199. data/spec/generators/install_generator_spec.rb +0 -31
  200. data/spec/generators/migration_generator_spec.rb +0 -20
  201. data/spec/generators/templates/routes.rb +0 -3
  202. data/spec/generators/views_generator_spec.rb +0 -27
  203. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -24
  204. data/spec/lib/config_spec.rb +0 -334
  205. data/spec/lib/doorkeeper_spec.rb +0 -28
  206. data/spec/lib/models/expirable_spec.rb +0 -51
  207. data/spec/lib/models/revocable_spec.rb +0 -59
  208. data/spec/lib/models/scopes_spec.rb +0 -43
  209. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -42
  210. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -80
  211. data/spec/lib/oauth/client/credentials_spec.rb +0 -47
  212. data/spec/lib/oauth/client/methods_spec.rb +0 -54
  213. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -44
  214. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -86
  215. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -54
  216. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  217. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -104
  218. data/spec/lib/oauth/client_spec.rb +0 -39
  219. data/spec/lib/oauth/code_request_spec.rb +0 -45
  220. data/spec/lib/oauth/code_response_spec.rb +0 -34
  221. data/spec/lib/oauth/error_response_spec.rb +0 -61
  222. data/spec/lib/oauth/error_spec.rb +0 -23
  223. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -23
  224. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -64
  225. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -20
  226. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -104
  227. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -28
  228. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -90
  229. data/spec/lib/oauth/pre_authorization_spec.rb +0 -155
  230. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -154
  231. data/spec/lib/oauth/scopes_spec.rb +0 -122
  232. data/spec/lib/oauth/token_request_spec.rb +0 -98
  233. data/spec/lib/oauth/token_response_spec.rb +0 -85
  234. data/spec/lib/oauth/token_spec.rb +0 -116
  235. data/spec/lib/request/strategy_spec.rb +0 -53
  236. data/spec/lib/server_spec.rb +0 -52
  237. data/spec/models/doorkeeper/access_grant_spec.rb +0 -36
  238. data/spec/models/doorkeeper/access_token_spec.rb +0 -394
  239. data/spec/models/doorkeeper/application_spec.rb +0 -179
  240. data/spec/requests/applications/applications_request_spec.rb +0 -94
  241. data/spec/requests/applications/authorized_applications_spec.rb +0 -30
  242. data/spec/requests/endpoints/authorization_spec.rb +0 -72
  243. data/spec/requests/endpoints/token_spec.rb +0 -64
  244. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -66
  245. data/spec/requests/flows/authorization_code_spec.rb +0 -156
  246. data/spec/requests/flows/client_credentials_spec.rb +0 -58
  247. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -32
  248. data/spec/requests/flows/implicit_grant_spec.rb +0 -61
  249. data/spec/requests/flows/password_spec.rb +0 -115
  250. data/spec/requests/flows/refresh_token_spec.rb +0 -174
  251. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  252. data/spec/requests/flows/skip_authorization_spec.rb +0 -59
  253. data/spec/requests/protected_resources/metal_spec.rb +0 -14
  254. data/spec/requests/protected_resources/private_api_spec.rb +0 -81
  255. data/spec/routing/custom_controller_routes_spec.rb +0 -71
  256. data/spec/routing/default_routes_spec.rb +0 -35
  257. data/spec/routing/scoped_routes_spec.rb +0 -31
  258. data/spec/spec_helper.rb +0 -2
  259. data/spec/spec_helper_integration.rb +0 -59
  260. data/spec/support/dependencies/factory_girl.rb +0 -2
  261. data/spec/support/helpers/access_token_request_helper.rb +0 -11
  262. data/spec/support/helpers/authorization_request_helper.rb +0 -41
  263. data/spec/support/helpers/config_helper.rb +0 -9
  264. data/spec/support/helpers/model_helper.rb +0 -67
  265. data/spec/support/helpers/request_spec_helper.rb +0 -76
  266. data/spec/support/helpers/url_helper.rb +0 -55
  267. data/spec/support/http_method_shim.rb +0 -24
  268. data/spec/support/orm/active_record.rb +0 -3
  269. data/spec/support/shared/controllers_shared_context.rb +0 -69
  270. data/spec/support/shared/models_shared_examples.rb +0 -52
  271. data/spec/validators/redirect_uri_validator_spec.rb +0 -78
@@ -1,21 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Models
3
5
  module Expirable
6
+ # Indicates whether the object is expired (`#expires_in` present and
7
+ # expiration time has come).
8
+ #
9
+ # @return [Boolean] true if object expired and false in other case
4
10
  def expired?
5
- expires_in && Time.now.utc > expired_time
11
+ !!(expires_in && Time.now.utc > expires_at)
6
12
  end
7
13
 
14
+ # Calculates expiration time in seconds.
15
+ #
16
+ # @return [Integer, nil] number of seconds if object has expiration time
17
+ # or nil if object never expires.
8
18
  def expires_in_seconds
9
19
  return nil if expires_in.nil?
10
- expires = (created_at + expires_in.seconds) - Time.now.utc
20
+
21
+ expires = expires_at - Time.now.utc
11
22
  expires_sec = expires.seconds.round(0)
12
23
  expires_sec > 0 ? expires_sec : 0
13
24
  end
14
25
 
15
- private
16
-
17
- def expired_time
18
- created_at + expires_in.seconds
26
+ # Expiration time (date time of creation + TTL).
27
+ #
28
+ # @return [Time, nil] expiration time in UTC
29
+ # or nil if the object never expires.
30
+ #
31
+ def expires_at
32
+ expires_in && created_at + expires_in.seconds
19
33
  end
20
34
  end
21
35
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module Orderable
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def ordered_by(attribute, direction = :asc)
10
+ order(attribute => direction)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,20 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Models
3
5
  module Ownership
4
6
  extend ActiveSupport::Concern
5
7
 
6
8
  included do
7
- belongs_to_options = { polymorphic: true }
8
- if defined?(ActiveRecord::Base) && ActiveRecord::VERSION::MAJOR >= 5
9
- belongs_to_options[:optional] = true
10
- end
11
-
12
- belongs_to :owner, belongs_to_options
9
+ belongs_to :owner, polymorphic: true, optional: true
13
10
  validates :owner, presence: true, if: :validate_owner?
14
11
  end
15
12
 
16
13
  def validate_owner?
17
- Doorkeeper.configuration.confirm_application_owner?
14
+ Doorkeeper.config.confirm_application_owner?
18
15
  end
19
16
  end
20
17
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module ResourceOwnerable
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ # Searches for record by Resource Owner considering Doorkeeper
10
+ # configuration for resource owner association.
11
+ #
12
+ # @param resource_owner [ActiveRecord::Base, Integer]
13
+ # resource owner
14
+ #
15
+ # @return [Doorkeeper::AccessGrant, Doorkeeper::AccessToken]
16
+ # collection of records
17
+ #
18
+ def by_resource_owner(resource_owner)
19
+ if Doorkeeper.configuration.polymorphic_resource_owner?
20
+ where(resource_owner: resource_owner)
21
+ else
22
+ where(resource_owner_id: resource_owner_id_for(resource_owner))
23
+ end
24
+ end
25
+
26
+ protected
27
+
28
+ # Backward compatible way to retrieve resource owner itself (if
29
+ # polymorphic association enabled) or just it's ID.
30
+ #
31
+ # @param resource_owner [ActiveRecord::Base, Integer]
32
+ # resource owner
33
+ #
34
+ # @return [ActiveRecord::Base, Integer]
35
+ # instance of Resource Owner or it's ID
36
+ #
37
+ def resource_owner_id_for(resource_owner)
38
+ if resource_owner.respond_to?(:to_key)
39
+ resource_owner.id
40
+ else
41
+ resource_owner
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module Reusable
6
+ # Indicates whether the object is reusable (i.e. It is not expired and
7
+ # has not crossed reuse_limit).
8
+ #
9
+ # @return [Boolean] true if can be reused and false in other case
10
+ def reusable?
11
+ return false if expired?
12
+ return true unless expires_in
13
+
14
+ threshold_limit = 100 - Doorkeeper.config.token_reuse_limit
15
+ expires_in_seconds >= threshold_limit * expires_in / 100
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,30 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Models
3
5
  module Revocable
6
+ # Revokes the object (updates `:revoked_at` attribute setting its value
7
+ # to the specific time).
8
+ #
9
+ # @param clock [Time] time object
10
+ #
4
11
  def revoke(clock = Time)
5
- update_attribute :revoked_at, clock.now.utc
12
+ update_attribute(:revoked_at, clock.now.utc)
6
13
  end
7
14
 
15
+ # Indicates whether the object has been revoked.
16
+ #
17
+ # @return [Boolean] true if revoked, false in other case
18
+ #
8
19
  def revoked?
9
20
  !!(revoked_at && revoked_at <= Time.now.utc)
10
21
  end
11
-
12
- def revoke_previous_refresh_token!
13
- return unless refresh_token_revoked_on_use?
14
- old_refresh_token.revoke if old_refresh_token
15
- update_attribute :previous_refresh_token, ""
16
- end
17
-
18
- private
19
-
20
- def old_refresh_token
21
- @old_refresh_token ||=
22
- AccessToken.by_refresh_token(previous_refresh_token)
23
- end
24
-
25
- def refresh_token_revoked_on_use?
26
- AccessToken.refresh_token_revoked_on_use?
27
- end
28
22
  end
29
23
  end
30
24
  end
@@ -1,8 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Models
3
5
  module Scopes
4
6
  def scopes
5
- OAuth::Scopes.from_string(self[:scopes])
7
+ OAuth::Scopes.from_string(scopes_string)
8
+ end
9
+
10
+ def scopes=(value)
11
+ if value.is_a?(Array)
12
+ super(Doorkeeper::OAuth::Scopes.from_array(value).to_s)
13
+ else
14
+ super(Doorkeeper::OAuth::Scopes.from_string(value.to_s).to_s)
15
+ end
6
16
  end
7
17
 
8
18
  def scopes_string
@@ -10,7 +20,7 @@ module Doorkeeper
10
20
  end
11
21
 
12
22
  def includes_scope?(*required_scopes)
13
- required_scopes.blank? || required_scopes.any? { |s| scopes.exists?(s.to_s) }
23
+ required_scopes.blank? || required_scopes.any? { |scope| scopes.exists?(scope.to_s) }
14
24
  end
15
25
  end
16
26
  end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ ##
6
+ # Storable finder to provide lookups for input plaintext values which are
7
+ # mapped to their stored versions (e.g., hashing, encryption) before lookup.
8
+ module SecretStorable
9
+ extend ActiveSupport::Concern
10
+
11
+ delegate :secret_strategy,
12
+ :fallback_secret_strategy,
13
+ to: :class
14
+
15
+ # :nodoc
16
+ module ClassMethods
17
+ # Compare the given plaintext with the secret
18
+ #
19
+ # @param input [String]
20
+ # The plain input to compare.
21
+ #
22
+ # @param secret [String]
23
+ # The secret value to compare with.
24
+ #
25
+ # @return [Boolean]
26
+ # Whether input matches secret as per the secret strategy
27
+ #
28
+ delegate :secret_matches?, to: :secret_strategy
29
+
30
+ # Returns an instance of the Doorkeeper::AccessToken with
31
+ # specific token value.
32
+ #
33
+ # @param attr [Symbol]
34
+ # The token attribute we're looking with.
35
+ #
36
+ # @param token [#to_s]
37
+ # token value (any object that responds to `#to_s`)
38
+ #
39
+ # @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
40
+ # if there is no record with such token
41
+ #
42
+ def find_by_plaintext_token(attr, token)
43
+ token = token.to_s
44
+
45
+ find_by(attr => secret_strategy.transform_secret(token)) ||
46
+ find_by_fallback_token(attr, token)
47
+ end
48
+
49
+ # Allow looking up previously plain tokens as a fallback
50
+ # IFF a fallback strategy has been defined
51
+ #
52
+ # @param attr [Symbol]
53
+ # The token attribute we're looking with.
54
+ #
55
+ # @param plain_secret [#to_s]
56
+ # plain secret value (any object that responds to `#to_s`)
57
+ #
58
+ # @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
59
+ # if there is no record with such token
60
+ #
61
+ def find_by_fallback_token(attr, plain_secret)
62
+ return nil unless fallback_secret_strategy
63
+
64
+ # Use the previous strategy to look up
65
+ stored_token = fallback_secret_strategy.transform_secret(plain_secret)
66
+ find_by(attr => stored_token).tap do |resource|
67
+ return nil unless resource
68
+
69
+ upgrade_fallback_value resource, attr, plain_secret
70
+ end
71
+ end
72
+
73
+ # Allow implementations in ORMs to replace a plain
74
+ # value falling back to to avoid it remaining as plain text.
75
+ #
76
+ # @param instance
77
+ # An instance of this model with a plain value token.
78
+ #
79
+ # @param attr
80
+ # The secret attribute name to upgrade.
81
+ #
82
+ # @param plain_secret
83
+ # The plain secret to upgrade.
84
+ #
85
+ def upgrade_fallback_value(instance, attr, plain_secret)
86
+ upgraded = secret_strategy.store_secret(instance, attr, plain_secret)
87
+ instance.update(attr => upgraded)
88
+ end
89
+
90
+ ##
91
+ # Determines the secret storing transformer
92
+ # Unless configured otherwise, uses the plain secret strategy
93
+ def secret_strategy
94
+ ::Doorkeeper::SecretStoring::Plain
95
+ end
96
+
97
+ ##
98
+ # Determine the fallback storing strategy
99
+ # Unless configured, there will be no fallback
100
+ def fallback_secret_strategy
101
+ nil
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -1,30 +1,66 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  module Authorization
4
6
  class Code
5
- attr_accessor :pre_auth, :resource_owner, :token
7
+ attr_reader :pre_auth, :resource_owner, :token
6
8
 
7
9
  def initialize(pre_auth, resource_owner)
8
- @pre_auth = pre_auth
10
+ @pre_auth = pre_auth
9
11
  @resource_owner = resource_owner
10
12
  end
11
13
 
12
- def issue_token
13
- @token ||= AccessGrant.create!(
14
+ def issue_token!
15
+ return @token if defined?(@token)
16
+
17
+ @token = Doorkeeper.config.access_grant_model.create!(access_grant_attributes)
18
+ end
19
+
20
+ def oob_redirect
21
+ { action: :show, code: token.plaintext_token }
22
+ end
23
+
24
+ def access_grant?
25
+ true
26
+ end
27
+
28
+ private
29
+
30
+ def authorization_code_expires_in
31
+ Doorkeeper.config.authorization_code_expires_in
32
+ end
33
+
34
+ def access_grant_attributes
35
+ attributes = {
14
36
  application_id: pre_auth.client.id,
15
- resource_owner_id: resource_owner.id,
16
- expires_in: configuration.authorization_code_expires_in,
37
+ expires_in: authorization_code_expires_in,
17
38
  redirect_uri: pre_auth.redirect_uri,
18
- scopes: pre_auth.scopes.to_s
19
- )
39
+ scopes: pre_auth.scopes.to_s,
40
+ }
41
+
42
+ if Doorkeeper.config.polymorphic_resource_owner?
43
+ attributes[:resource_owner] = resource_owner
44
+ else
45
+ attributes[:resource_owner_id] = resource_owner.id
46
+ end
47
+
48
+ pkce_attributes.merge(attributes)
20
49
  end
21
50
 
22
- def native_redirect
23
- { action: :show, code: token.token }
51
+ def pkce_attributes
52
+ return {} unless pkce_supported?
53
+
54
+ {
55
+ code_challenge: pre_auth.code_challenge,
56
+ code_challenge_method: pre_auth.code_challenge_method,
57
+ }
24
58
  end
25
59
 
26
- def configuration
27
- Doorkeeper.configuration
60
+ # Ensures firstly, if migration with additional PKCE columns was
61
+ # generated and migrated
62
+ def pkce_supported?
63
+ Doorkeeper.config.access_grant_model.pkce_supported?
28
64
  end
29
65
  end
30
66
  end
@@ -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,54 +1,92 @@
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
8
+
9
+ class << self
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)
14
+ pre_auth_or_oauth_client.client
15
+ else
16
+ pre_auth_or_oauth_client
17
+ end
18
+
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
44
+ end
45
+ end
6
46
 
7
47
  def initialize(pre_auth, resource_owner)
8
48
  @pre_auth = pre_auth
9
49
  @resource_owner = resource_owner
10
50
  end
11
51
 
12
- def self.access_token_expires_in(server, pre_auth_or_oauth_client)
13
- if expiration = custom_expiration(server, pre_auth_or_oauth_client)
14
- expiration
15
- else
16
- server.access_token_expires_in
17
- end
18
- end
52
+ def issue_token!
53
+ return @token if defined?(@token)
19
54
 
20
- def issue_token
21
- @token ||= AccessToken.find_or_create_for(
55
+ context = self.class.build_context(
22
56
  pre_auth.client,
23
- resource_owner.id,
57
+ Doorkeeper::OAuth::IMPLICIT,
24
58
  pre_auth.scopes,
25
- self.class.access_token_expires_in(configuration, pre_auth),
26
- 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,
27
68
  )
28
69
  end
29
70
 
30
- def native_redirect
71
+ def oob_redirect
31
72
  {
32
- controller: 'doorkeeper/token_info',
73
+ controller: controller,
33
74
  action: :show,
34
- access_token: token.token
75
+ access_token: token.plaintext_token,
35
76
  }
36
77
  end
37
78
 
38
- private
39
-
40
- def self.custom_expiration(server, pre_auth_or_oauth_client)
41
- oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
42
- pre_auth_or_oauth_client.client
43
- else
44
- pre_auth_or_oauth_client
45
- end
46
-
47
- server.custom_access_token_expires_in.call(oauth_client)
79
+ def access_token?
80
+ true
48
81
  end
49
82
 
50
- def configuration
51
- Doorkeeper.configuration
83
+ private
84
+
85
+ def controller
86
+ @controller ||= begin
87
+ mapping = Doorkeeper::Rails::Routes.mapping[:token_info] || {}
88
+ mapping[:controllers] || "doorkeeper/token_info"
89
+ end
52
90
  end
53
91
  end
54
92
  end
@@ -1,27 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/utils"
4
+
1
5
  module Doorkeeper
2
6
  module OAuth
3
7
  module Authorization
4
- module URIBuilder
5
- include Rack::Utils
8
+ class URIBuilder
9
+ class << self
10
+ def uri_with_query(url, parameters = {})
11
+ uri = URI.parse(url)
12
+ original_query = Rack::Utils.parse_query(uri.query)
13
+ uri.query = build_query(original_query.merge(parameters))
14
+ uri.to_s
15
+ end
6
16
 
7
- extend self
17
+ def uri_with_fragment(url, parameters = {})
18
+ uri = URI.parse(url)
19
+ uri.fragment = build_query(parameters)
20
+ uri.to_s
21
+ end
8
22
 
9
- def uri_with_query(url, parameters = {})
10
- uri = URI.parse(url)
11
- original_query = parse_query(uri.query)
12
- uri.query = build_query(original_query.merge(parameters))
13
- uri.to_s
14
- end
15
-
16
- def uri_with_fragment(url, parameters = {})
17
- uri = URI.parse(url)
18
- uri.fragment = build_query(parameters)
19
- uri.to_s
20
- end
23
+ private
21
24
 
22
- def build_query(parameters = {})
23
- parameters = parameters.reject { |_, v| v.blank? }
24
- super parameters
25
+ def build_query(parameters = {})
26
+ parameters.reject! { |_, value| value.blank? }
27
+ Rack::Utils.build_query(parameters)
28
+ end
25
29
  end
26
30
  end
27
31
  end