doorkeeper 5.0.3 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/.hound.yml +2 -1
  3. data/.rubocop.yml +37 -4
  4. data/.travis.yml +11 -21
  5. data/Appraisals +29 -7
  6. data/Dangerfile +5 -2
  7. data/Gemfile +19 -5
  8. data/NEWS.md +81 -21
  9. data/README.md +75 -485
  10. data/Rakefile +10 -8
  11. data/app/controllers/doorkeeper/application_controller.rb +1 -2
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -13
  13. data/app/controllers/doorkeeper/applications_controller.rb +20 -8
  14. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  15. data/app/controllers/doorkeeper/token_info_controller.rb +2 -2
  16. data/app/controllers/doorkeeper/tokens_controller.rb +11 -11
  17. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  18. data/app/validators/redirect_uri_validator.rb +5 -2
  19. data/app/views/doorkeeper/applications/_form.html.erb +6 -0
  20. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  21. data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
  22. data/bin/console +16 -0
  23. data/config/locales/en.yml +1 -0
  24. data/doorkeeper.gemspec +24 -21
  25. data/gemfiles/rails_5_0.gemfile +9 -4
  26. data/gemfiles/rails_5_1.gemfile +9 -4
  27. data/gemfiles/rails_5_2.gemfile +10 -5
  28. data/gemfiles/rails_6_0.gemfile +17 -0
  29. data/gemfiles/rails_master.gemfile +9 -9
  30. data/lib/doorkeeper/config/option.rb +64 -0
  31. data/lib/doorkeeper/config.rb +191 -75
  32. data/lib/doorkeeper/engine.rb +1 -1
  33. data/lib/doorkeeper/grape/authorization_decorator.rb +4 -4
  34. data/lib/doorkeeper/grape/helpers.rb +3 -3
  35. data/lib/doorkeeper/helpers/controller.rb +3 -2
  36. data/lib/doorkeeper/models/access_grant_mixin.rb +20 -3
  37. data/lib/doorkeeper/models/access_token_mixin.rb +63 -19
  38. data/lib/doorkeeper/models/application_mixin.rb +43 -1
  39. data/lib/doorkeeper/models/concerns/expirable.rb +4 -2
  40. data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
  41. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  42. data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
  43. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  44. data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
  45. data/lib/doorkeeper/oauth/authorization/code.rb +2 -2
  46. data/lib/doorkeeper/oauth/authorization/token.rb +12 -7
  47. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
  48. data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -4
  49. data/lib/doorkeeper/oauth/client.rb +1 -1
  50. data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -4
  51. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
  52. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  53. data/lib/doorkeeper/oauth/error_response.rb +10 -6
  54. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  55. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
  56. data/lib/doorkeeper/oauth/helpers/unique_token.rb +13 -1
  57. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +37 -1
  58. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -1
  59. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  60. data/lib/doorkeeper/oauth/pre_authorization.rb +11 -5
  61. data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
  62. data/lib/doorkeeper/oauth/scopes.rb +5 -3
  63. data/lib/doorkeeper/oauth/token.rb +2 -2
  64. data/lib/doorkeeper/oauth/token_introspection.rb +74 -8
  65. data/lib/doorkeeper/oauth/token_response.rb +9 -9
  66. data/lib/doorkeeper/oauth.rb +5 -5
  67. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
  68. data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
  69. data/lib/doorkeeper/orm/active_record/application.rb +21 -57
  70. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
  71. data/lib/doorkeeper/orm/active_record.rb +6 -6
  72. data/lib/doorkeeper/rails/helpers.rb +1 -1
  73. data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
  74. data/lib/doorkeeper/rails/routes.rb +11 -11
  75. data/lib/doorkeeper/rake/db.rake +13 -13
  76. data/lib/doorkeeper/rake.rb +1 -1
  77. data/lib/doorkeeper/request.rb +1 -1
  78. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  79. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  80. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  81. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  82. data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
  83. data/lib/doorkeeper/version.rb +3 -3
  84. data/lib/doorkeeper.rb +69 -60
  85. data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
  86. data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
  87. data/lib/generators/doorkeeper/install_generator.rb +11 -9
  88. data/lib/generators/doorkeeper/migration_generator.rb +9 -9
  89. data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
  90. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
  91. data/lib/generators/doorkeeper/templates/initializer.rb +120 -13
  92. data/lib/generators/doorkeeper/templates/migration.rb.erb +15 -7
  93. data/lib/generators/doorkeeper/views_generator.rb +6 -4
  94. data/spec/controllers/application_metal_controller_spec.rb +24 -10
  95. data/spec/controllers/applications_controller_spec.rb +54 -52
  96. data/spec/controllers/authorizations_controller_spec.rb +139 -145
  97. data/spec/controllers/protected_resources_controller_spec.rb +78 -76
  98. data/spec/controllers/token_info_controller_spec.rb +14 -12
  99. data/spec/controllers/tokens_controller_spec.rb +167 -108
  100. data/spec/dummy/Rakefile +3 -1
  101. data/spec/dummy/app/controllers/application_controller.rb +3 -1
  102. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +2 -0
  103. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
  104. data/spec/dummy/app/controllers/home_controller.rb +5 -3
  105. data/spec/dummy/app/controllers/metal_controller.rb +2 -0
  106. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
  107. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  108. data/spec/dummy/app/models/user.rb +2 -0
  109. data/spec/dummy/config/application.rb +25 -1
  110. data/spec/dummy/config/environments/development.rb +2 -0
  111. data/spec/dummy/config/environments/production.rb +2 -0
  112. data/spec/dummy/config/environments/test.rb +3 -1
  113. data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
  114. data/spec/dummy/config/initializers/doorkeeper.rb +5 -2
  115. data/spec/dummy/config/initializers/secret_token.rb +3 -1
  116. data/spec/dummy/config/initializers/session_store.rb +3 -1
  117. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
  118. data/spec/dummy/config.ru +3 -1
  119. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +17 -10
  120. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
  121. data/spec/dummy/db/schema.rb +1 -1
  122. data/spec/dummy/script/rails +5 -3
  123. data/spec/factories.rb +8 -6
  124. data/spec/generators/application_owner_generator_spec.rb +13 -26
  125. data/spec/generators/confidential_applications_generator_spec.rb +12 -28
  126. data/spec/generators/install_generator_spec.rb +17 -15
  127. data/spec/generators/migration_generator_spec.rb +13 -26
  128. data/spec/generators/pkce_generator_spec.rb +11 -26
  129. data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
  130. data/spec/generators/templates/routes.rb +2 -0
  131. data/spec/generators/views_generator_spec.rb +14 -12
  132. data/spec/grape/grape_integration_spec.rb +34 -32
  133. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
  134. data/spec/lib/config_spec.rb +268 -99
  135. data/spec/lib/doorkeeper_spec.rb +3 -1
  136. data/spec/lib/models/expirable_spec.rb +22 -8
  137. data/spec/lib/models/reusable_spec.rb +40 -0
  138. data/spec/lib/models/revocable_spec.rb +8 -6
  139. data/spec/lib/models/scopes_spec.rb +27 -13
  140. data/spec/lib/models/secret_storable_spec.rb +135 -0
  141. data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
  142. data/spec/lib/oauth/authorization_code_request_spec.rb +34 -11
  143. data/spec/lib/oauth/base_request_spec.rb +20 -8
  144. data/spec/lib/oauth/base_response_spec.rb +3 -1
  145. data/spec/lib/oauth/client/credentials_spec.rb +24 -22
  146. data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
  147. data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
  148. data/spec/lib/oauth/client_credentials/validation_spec.rb +20 -15
  149. data/spec/lib/oauth/client_credentials_integration_spec.rb +7 -5
  150. data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
  151. data/spec/lib/oauth/client_spec.rb +15 -13
  152. data/spec/lib/oauth/code_request_spec.rb +8 -6
  153. data/spec/lib/oauth/code_response_spec.rb +9 -7
  154. data/spec/lib/oauth/error_response_spec.rb +19 -11
  155. data/spec/lib/oauth/error_spec.rb +4 -2
  156. data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
  157. data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
  158. data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
  159. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -95
  160. data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
  161. data/spec/lib/oauth/password_access_token_request_spec.rb +79 -30
  162. data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
  163. data/spec/lib/oauth/refresh_token_request_spec.rb +36 -33
  164. data/spec/lib/oauth/scopes_spec.rb +63 -61
  165. data/spec/lib/oauth/token_request_spec.rb +79 -24
  166. data/spec/lib/oauth/token_response_spec.rb +40 -38
  167. data/spec/lib/oauth/token_spec.rb +60 -44
  168. data/spec/lib/request/strategy_spec.rb +3 -1
  169. data/spec/lib/secret_storing/base_spec.rb +60 -0
  170. data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
  171. data/spec/lib/secret_storing/plain_spec.rb +44 -0
  172. data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
  173. data/spec/lib/server_spec.rb +16 -14
  174. data/spec/lib/stale_records_cleaner_spec.rb +17 -17
  175. data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
  176. data/spec/models/doorkeeper/access_token_spec.rb +198 -73
  177. data/spec/models/doorkeeper/application_spec.rb +280 -288
  178. data/spec/requests/applications/applications_request_spec.rb +98 -66
  179. data/spec/requests/applications/authorized_applications_spec.rb +20 -18
  180. data/spec/requests/endpoints/authorization_spec.rb +25 -23
  181. data/spec/requests/endpoints/token_spec.rb +38 -36
  182. data/spec/requests/flows/authorization_code_errors_spec.rb +26 -24
  183. data/spec/requests/flows/authorization_code_spec.rb +193 -151
  184. data/spec/requests/flows/client_credentials_spec.rb +54 -52
  185. data/spec/requests/flows/implicit_grant_errors_spec.rb +10 -8
  186. data/spec/requests/flows/implicit_grant_spec.rb +27 -25
  187. data/spec/requests/flows/password_spec.rb +59 -55
  188. data/spec/requests/flows/refresh_token_spec.rb +45 -43
  189. data/spec/requests/flows/revoke_token_spec.rb +40 -54
  190. data/spec/requests/flows/skip_authorization_spec.rb +23 -21
  191. data/spec/requests/protected_resources/metal_spec.rb +7 -5
  192. data/spec/requests/protected_resources/private_api_spec.rb +35 -33
  193. data/spec/routing/custom_controller_routes_spec.rb +71 -65
  194. data/spec/routing/default_routes_spec.rb +22 -20
  195. data/spec/routing/scoped_routes_spec.rb +20 -18
  196. data/spec/spec_helper.rb +15 -13
  197. data/spec/spec_helper_integration.rb +3 -1
  198. data/spec/support/dependencies/factory_bot.rb +3 -1
  199. data/spec/support/doorkeeper_rspec.rb +3 -1
  200. data/spec/support/helpers/access_token_request_helper.rb +3 -1
  201. data/spec/support/helpers/authorization_request_helper.rb +4 -2
  202. data/spec/support/helpers/config_helper.rb +2 -0
  203. data/spec/support/helpers/model_helper.rb +3 -1
  204. data/spec/support/helpers/request_spec_helper.rb +5 -3
  205. data/spec/support/helpers/url_helper.rb +9 -7
  206. data/spec/support/http_method_shim.rb +4 -9
  207. data/spec/support/orm/active_record.rb +3 -1
  208. data/spec/support/shared/controllers_shared_context.rb +18 -16
  209. data/spec/support/shared/hashing_shared_context.rb +36 -0
  210. data/spec/support/shared/models_shared_examples.rb +12 -10
  211. data/spec/validators/redirect_uri_validator_spec.rb +74 -45
  212. data/spec/version/version_spec.rb +7 -5
  213. metadata +60 -26
  214. data/gemfiles/rails_4_2.gemfile +0 -13
  215. data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
@@ -1,12 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  class Application < ActiveRecord::Base
3
- self.table_name = "#{table_name_prefix}oauth_applications#{table_name_suffix}".to_sym
5
+ self.table_name = "#{table_name_prefix}oauth_applications#{table_name_suffix}"
4
6
 
5
7
  include ApplicationMixin
6
- include ActiveModel::MassAssignmentSecurity if defined?(::ProtectedAttributes)
7
8
 
8
- has_many :access_grants, dependent: :delete_all, class_name: 'Doorkeeper::AccessGrant'
9
- has_many :access_tokens, dependent: :delete_all, class_name: 'Doorkeeper::AccessToken'
9
+ has_many :access_grants, dependent: :delete_all, class_name: "Doorkeeper::AccessGrant"
10
+ has_many :access_tokens, dependent: :delete_all, class_name: "Doorkeeper::AccessToken"
10
11
 
11
12
  validates :name, :secret, :uid, presence: true
12
13
  validates :uid, uniqueness: true
@@ -17,7 +18,7 @@ module Doorkeeper
17
18
 
18
19
  before_validation :generate_uid, :generate_secret, on: :create
19
20
 
20
- has_many :authorized_tokens, -> { where(revoked_at: nil) }, class_name: 'AccessToken'
21
+ has_many :authorized_tokens, -> { where(revoked_at: nil) }, class_name: "AccessToken"
21
22
  has_many :authorized_applications, through: :authorized_tokens, source: :application
22
23
 
23
24
  # Returns Applications associated with active (not revoked) Access Tokens
@@ -45,26 +46,17 @@ module Doorkeeper
45
46
  AccessGrant.revoke_all_for(id, resource_owner)
46
47
  end
47
48
 
48
- # Represents client as set of it's attributes in JSON format.
49
- # This is the right way how we want to override ActiveRecord #to_json.
50
- #
51
- # Respects privacy settings and serializes minimum set of attributes
52
- # for public/private clients and full set for authorized owners.
53
- #
54
- # @return [Hash] entity attributes for JSON
49
+ # We keep a volatile copy of the raw secret for initial communication
50
+ # The stored refresh_token may be mapped and not available in cleartext.
55
51
  #
56
- def as_json(options = {})
57
- # if application belongs to some owner we need to check if it's the same as
58
- # the one passed in the options or check if we render the client as an owner
59
- if (respond_to?(:owner) && owner && owner == options[:current_resource_owner]) ||
60
- options[:as_owner]
61
- # Owners can see all the client attributes, fallback to ActiveModel serialization
62
- super
52
+ # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
53
+ # while hashing strategies do not, so you cannot rely on this value
54
+ # returning a present value for persisted tokens.
55
+ def plaintext_secret
56
+ if secret_strategy.allows_restoring_secrets?
57
+ secret_strategy.restore_secret(self, :secret)
63
58
  else
64
- # if application has no owner or it's owner doesn't match one from the options
65
- # we render only minimum set of attributes that could be exposed to a public
66
- only = extract_serializable_attributes(options)
67
- super(options.merge(only: only))
59
+ @raw_secret
68
60
  end
69
61
  end
70
62
 
@@ -75,12 +67,16 @@ module Doorkeeper
75
67
  end
76
68
 
77
69
  def generate_secret
78
- self.secret = UniqueToken.generate if secret.blank?
70
+ return unless secret.blank?
71
+
72
+ @raw_secret = UniqueToken.generate
73
+ secret_strategy.store_secret(self, :secret, @raw_secret)
79
74
  end
80
75
 
81
76
  def scopes_match_configured
82
77
  if scopes.present? &&
83
- !ScopeChecker.valid?(scopes.to_s, Doorkeeper.configuration.scopes)
78
+ !ScopeChecker.valid?(scope_str: scopes.to_s,
79
+ server_scopes: Doorkeeper.configuration.scopes)
84
80
  errors.add(:scopes, :not_match_configured)
85
81
  end
86
82
  end
@@ -88,37 +84,5 @@ module Doorkeeper
88
84
  def enforce_scopes?
89
85
  Doorkeeper.configuration.enforce_configured_scopes?
90
86
  end
91
-
92
- # Helper method to extract collection of serializable attribute names
93
- # considering serialization options (like `only`, `except` and so on).
94
- #
95
- # @param options [Hash] serialization options
96
- #
97
- # @return [Array<String>]
98
- # collection of attributes to be serialized using #as_json
99
- #
100
- def extract_serializable_attributes(options = {})
101
- opts = options.try(:dup) || {}
102
- only = Array.wrap(opts[:only]).map(&:to_s)
103
-
104
- only = if only.blank?
105
- serializable_attributes
106
- else
107
- only & serializable_attributes
108
- end
109
-
110
- only -= Array.wrap(opts[:except]).map(&:to_s) if opts.key?(:except)
111
- only.uniq
112
- end
113
-
114
- # Collection of attributes that could be serialized for public.
115
- # Override this method if you need additional attributes to be serialized.
116
- #
117
- # @return [Array<String>] collection of serializable attributes
118
- def serializable_attributes
119
- attributes = %w[id name created_at]
120
- attributes << "uid" unless confidential?
121
- attributes
122
- end
123
87
  end
124
88
  end
@@ -3,22 +3,29 @@
3
3
  module Doorkeeper
4
4
  module Orm
5
5
  module ActiveRecord
6
+ # Helper class to clear stale and non-active tokens and grants.
7
+ # Used by Doorkeeper Rake tasks.
8
+ #
6
9
  class StaleRecordsCleaner
7
10
  def initialize(base_scope)
8
11
  @base_scope = base_scope
9
12
  end
10
13
 
14
+ # Clears revoked records
11
15
  def clean_revoked
12
16
  table = @base_scope.arel_table
17
+
13
18
  @base_scope.where.not(revoked_at: nil)
14
- .where(table[:revoked_at].lt(Time.current))
15
- .delete_all
19
+ .where(table[:revoked_at].lt(Time.current))
20
+ .in_batches(&:delete_all)
16
21
  end
17
22
 
23
+ # Clears expired records
18
24
  def clean_expired(ttl)
19
25
  table = @base_scope.arel_table
26
+
20
27
  @base_scope.where(table[:created_at].lt(Time.current - ttl))
21
- .delete_all
28
+ .in_batches(&:delete_all)
22
29
  end
23
30
  end
24
31
  end
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/lazy_load_hooks'
3
+ require "active_support/lazy_load_hooks"
4
4
 
5
- require 'doorkeeper/orm/active_record/stale_records_cleaner'
5
+ require "doorkeeper/orm/active_record/stale_records_cleaner"
6
6
 
7
7
  module Doorkeeper
8
8
  module Orm
9
9
  module ActiveRecord
10
10
  def self.initialize_models!
11
11
  lazy_load do
12
- require 'doorkeeper/orm/active_record/access_grant'
13
- require 'doorkeeper/orm/active_record/access_token'
14
- require 'doorkeeper/orm/active_record/application'
12
+ require "doorkeeper/orm/active_record/access_grant"
13
+ require "doorkeeper/orm/active_record/access_token"
14
+ require "doorkeeper/orm/active_record/application"
15
15
 
16
16
  if Doorkeeper.configuration.active_record_options[:establish_connection]
17
17
  [Doorkeeper::AccessGrant, Doorkeeper::AccessToken, Doorkeeper::Application].each do |model|
@@ -24,7 +24,7 @@ module Doorkeeper
24
24
 
25
25
  def self.initialize_application_owner!
26
26
  lazy_load do
27
- require 'doorkeeper/models/concerns/ownership'
27
+ require "doorkeeper/models/concerns/ownership"
28
28
 
29
29
  Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
30
30
  end
@@ -14,7 +14,7 @@ module Doorkeeper
14
14
  def doorkeeper_forbidden_render_options(**); end
15
15
 
16
16
  def valid_doorkeeper_token?
17
- doorkeeper_token && doorkeeper_token.acceptable?(@_doorkeeper_scopes)
17
+ doorkeeper_token&.acceptable?(@_doorkeeper_scopes)
18
18
  end
19
19
 
20
20
  private
@@ -8,17 +8,17 @@ module Doorkeeper
8
8
 
9
9
  def initialize
10
10
  @controllers = {
11
- authorizations: 'doorkeeper/authorizations',
12
- applications: 'doorkeeper/applications',
13
- authorized_applications: 'doorkeeper/authorized_applications',
14
- tokens: 'doorkeeper/tokens',
15
- 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",
16
16
  }
17
17
 
18
18
  @as = {
19
19
  authorizations: :authorization,
20
20
  tokens: :token,
21
- token_info: :token_info
21
+ token_info: :token_info,
22
22
  }
23
23
 
24
24
  @skips = []
@@ -27,7 +27,7 @@ module Doorkeeper
27
27
  def [](routes)
28
28
  {
29
29
  controllers: @controllers[routes],
30
- as: @as[routes]
30
+ as: @as[routes],
31
31
  }
32
32
  end
33
33
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'doorkeeper/rails/routes/mapping'
4
- require 'doorkeeper/rails/routes/mapper'
3
+ require "doorkeeper/rails/routes/mapping"
4
+ require "doorkeeper/rails/routes/mapper"
5
5
 
6
6
  module Doorkeeper
7
7
  module Rails
@@ -32,7 +32,7 @@ module Doorkeeper
32
32
  end
33
33
 
34
34
  def generate_routes!(options)
35
- routes.scope options[:scope] || 'oauth', as: 'oauth' do
35
+ routes.scope options[:scope] || "oauth", as: "oauth" do
36
36
  map_route(:authorizations, :authorization_routes)
37
37
  map_route(:tokens, :token_routes)
38
38
  map_route(:tokens, :revoke_routes)
@@ -56,37 +56,37 @@ module Doorkeeper
56
56
  def authorization_routes(mapping)
57
57
  routes.resource(
58
58
  :authorization,
59
- path: 'authorize',
59
+ path: "authorize",
60
60
  only: %i[create destroy],
61
61
  as: mapping[:as],
62
62
  controller: mapping[:controllers]
63
63
  ) do
64
- routes.get '/native', action: :show, on: :member
65
- routes.get '/', action: :new, on: :member
64
+ routes.get "/native", action: :show, on: :member
65
+ routes.get "/", action: :new, on: :member
66
66
  end
67
67
  end
68
68
 
69
69
  def token_routes(mapping)
70
70
  routes.resource(
71
71
  :token,
72
- path: 'token',
72
+ path: "token",
73
73
  only: [:create], as: mapping[:as],
74
74
  controller: mapping[:controllers]
75
75
  )
76
76
  end
77
77
 
78
78
  def revoke_routes(mapping)
79
- routes.post 'revoke', controller: mapping[:controllers], action: :revoke
79
+ routes.post "revoke", controller: mapping[:controllers], action: :revoke
80
80
  end
81
81
 
82
82
  def introspect_routes(mapping)
83
- routes.post 'introspect', controller: mapping[:controllers], action: :introspect
83
+ routes.post "introspect", controller: mapping[:controllers], action: :introspect
84
84
  end
85
85
 
86
86
  def token_info_routes(mapping)
87
87
  routes.resource(
88
88
  :token_info,
89
- path: 'token/info',
89
+ path: "token/info",
90
90
  only: [:show], as: mapping[:as],
91
91
  controller: mapping[:controllers]
92
92
  )
@@ -96,7 +96,7 @@ module Doorkeeper
96
96
  routes.resources :doorkeeper_applications,
97
97
  controller: mapping[:controllers],
98
98
  as: :applications,
99
- path: 'applications'
99
+ path: "applications"
100
100
  end
101
101
 
102
102
  def authorized_applications_routes(mapping)
@@ -2,36 +2,36 @@
2
2
 
3
3
  namespace :doorkeeper do
4
4
  namespace :db do
5
- desc 'Removes stale data from doorkeeper related database tables'
5
+ desc "Removes stale data from doorkeeper related database tables"
6
6
  task cleanup: [
7
- 'doorkeeper:db:cleanup:revoked_tokens',
8
- 'doorkeeper:db:cleanup:expired_tokens',
9
- 'doorkeeper:db:cleanup:revoked_grants',
10
- 'doorkeeper:db:cleanup:expired_grants'
7
+ "doorkeeper:db:cleanup:revoked_tokens",
8
+ "doorkeeper:db:cleanup:expired_tokens",
9
+ "doorkeeper:db:cleanup:revoked_grants",
10
+ "doorkeeper:db:cleanup:expired_grants",
11
11
  ]
12
12
 
13
13
  namespace :cleanup do
14
- desc 'Removes stale access tokens'
15
- task revoked_tokens: 'doorkeeper:setup' do
14
+ desc "Removes stale access tokens"
15
+ task revoked_tokens: "doorkeeper:setup" do
16
16
  cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper::AccessToken)
17
17
  cleaner.clean_revoked
18
18
  end
19
19
 
20
- desc 'Removes expired (TTL passed) access tokens'
21
- task expired_tokens: 'doorkeeper:setup' do
20
+ desc "Removes expired (TTL passed) access tokens"
21
+ task expired_tokens: "doorkeeper:setup" do
22
22
  expirable_tokens = Doorkeeper::AccessToken.where(refresh_token: nil)
23
23
  cleaner = Doorkeeper::StaleRecordsCleaner.new(expirable_tokens)
24
24
  cleaner.clean_expired(Doorkeeper.configuration.access_token_expires_in)
25
25
  end
26
26
 
27
- desc 'Removes stale access grants'
28
- task revoked_grants: 'doorkeeper:setup' do
27
+ desc "Removes stale access grants"
28
+ task revoked_grants: "doorkeeper:setup" do
29
29
  cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
30
30
  cleaner.clean_revoked
31
31
  end
32
32
 
33
- desc 'Removes expired (TTL passed) access grants'
34
- task expired_grants: 'doorkeeper:setup' do
33
+ desc "Removes expired (TTL passed) access grants"
34
+ task expired_grants: "doorkeeper:setup" do
35
35
  cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
36
36
  cleaner.clean_expired(Doorkeeper.configuration.authorization_code_expires_in)
37
37
  end
@@ -4,7 +4,7 @@ module Doorkeeper
4
4
  module Rake
5
5
  class << self
6
6
  def load_tasks
7
- glob = File.join(File.absolute_path(__dir__), 'rake', '*.rake')
7
+ glob = File.join(File.absolute_path(__dir__), "rake", "*.rake")
8
8
  Dir[glob].each do |rake_file|
9
9
  load rake_file
10
10
  end
@@ -33,7 +33,7 @@ module Doorkeeper
33
33
  end
34
34
 
35
35
  def build_strategy_class(grant_or_request_type)
36
- strategy_class_name = grant_or_request_type.to_s.tr(' ', '_').camelize
36
+ strategy_class_name = grant_or_request_type.to_s.tr(" ", "_").camelize
37
37
  "Doorkeeper::Request::#{strategy_class_name}".constantize
38
38
  end
39
39
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module SecretStoring
5
+ ##
6
+ # Base class for secret storing, including common helpers
7
+ class Base
8
+ ##
9
+ # Return the value to be stored by the database
10
+ # used for looking up a database value.
11
+ # @param plain_secret The plain secret input / generated
12
+ def self.transform_secret(_plain_secret)
13
+ raise NotImplementedError
14
+ end
15
+
16
+ ##
17
+ # Transform and store the given secret attribute => value
18
+ # pair used for safely storing the attribute
19
+ # @param resource The model instance being modified
20
+ # @param attribute The secret attribute
21
+ # @param plain_secret The plain secret input / generated
22
+ def self.store_secret(resource, attribute, plain_secret)
23
+ transformed_value = transform_secret(plain_secret)
24
+ resource.public_send(:"#{attribute}=", transformed_value)
25
+
26
+ transformed_value
27
+ end
28
+
29
+ ##
30
+ # Return the restored value from the database
31
+ # @param resource The resource instance to act on
32
+ # @param attribute The secret attribute to restore
33
+ # as retrieved from the database.
34
+ def self.restore_secret(_resource, _attribute)
35
+ raise NotImplementedError
36
+ end
37
+
38
+ ##
39
+ # Determines whether this strategy supports restoring
40
+ # secrets from the database. This allows detecting users
41
+ # trying to use a non-restorable strategy with +reuse_access_tokens+.
42
+ def self.allows_restoring_secrets?
43
+ false
44
+ end
45
+
46
+ ##
47
+ # Determines what secrets this strategy is applicable for
48
+ def self.validate_for(model)
49
+ valid = %i[token application]
50
+ return true if valid.include?(model.to_sym)
51
+
52
+ raise ArgumentError, "'#{name}' can not be used for #{model}."
53
+ end
54
+
55
+ ##
56
+ # Securely compare the given +input+ value with a +stored+ value
57
+ # processed by +transform_secret+.
58
+ def self.secret_matches?(input, stored)
59
+ transformed_input = transform_secret(input)
60
+ ActiveSupport::SecurityUtils.secure_compare transformed_input, stored
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module SecretStoring
5
+ ##
6
+ # Plain text secret storing, which is the default
7
+ # but also provides fallback lookup if
8
+ # other secret storing mechanisms are enabled.
9
+ class BCrypt < Base
10
+ ##
11
+ # Return the value to be stored by the database
12
+ # @param plain_secret The plain secret input / generated
13
+ def self.transform_secret(plain_secret)
14
+ ::BCrypt::Password.create(plain_secret.to_s)
15
+ end
16
+
17
+ ##
18
+ # Securely compare the given +input+ value with a +stored+ value
19
+ # processed by +transform_secret+.
20
+ def self.secret_matches?(input, stored)
21
+ ::BCrypt::Password.new(stored.to_s) == input.to_s
22
+ rescue ::BCrypt::Errors::InvalidHash
23
+ false
24
+ end
25
+
26
+ ##
27
+ # Determines whether this strategy supports restoring
28
+ # secrets from the database. This allows detecting users
29
+ # trying to use a non-restorable strategy with +reuse_access_tokens+.
30
+ def self.allows_restoring_secrets?
31
+ false
32
+ end
33
+
34
+ ##
35
+ # Determines what secrets this strategy is applicable for
36
+ def self.validate_for(model)
37
+ unless model.to_sym == :application
38
+ raise ArgumentError,
39
+ "'#{name}' can only be used for storing application secrets."
40
+ end
41
+
42
+ unless bcrypt_present?
43
+ raise ArgumentError,
44
+ "'#{name}' requires the 'bcrypt' gem being loaded."
45
+ end
46
+
47
+ true
48
+ end
49
+
50
+ ##
51
+ # Test if we can require the BCrypt gem
52
+ def self.bcrypt_present?
53
+ require "bcrypt"
54
+ true
55
+ rescue LoadError
56
+ false
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module SecretStoring
5
+ ##
6
+ # Plain text secret storing, which is the default
7
+ # but also provides fallback lookup if
8
+ # other secret storing mechanisms are enabled.
9
+ class Plain < Base
10
+ ##
11
+ # Return the value to be stored by the database
12
+ # @param plain_secret The plain secret input / generated
13
+ def self.transform_secret(plain_secret)
14
+ plain_secret
15
+ end
16
+
17
+ ##
18
+ # Return the restored value from the database
19
+ # @param resource The resource instance to act on
20
+ # @param attribute The secret attribute to restore
21
+ # as retrieved from the database.
22
+ def self.restore_secret(resource, attribute)
23
+ resource.public_send(attribute)
24
+ end
25
+
26
+ ##
27
+ # Plain values obviously allow restoring
28
+ def self.allows_restoring_secrets?
29
+ true
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module SecretStoring
5
+ ##
6
+ # Plain text secret storing, which is the default
7
+ # but also provides fallback lookup if
8
+ # other secret storing mechanisms are enabled.
9
+ class Sha256Hash < Base
10
+ ##
11
+ # Return the value to be stored by the database
12
+ # @param plain_secret The plain secret input / generated
13
+ def self.transform_secret(plain_secret)
14
+ ::Digest::SHA256.hexdigest plain_secret
15
+ end
16
+
17
+ ##
18
+ # Determines whether this strategy supports restoring
19
+ # secrets from the database. This allows detecting users
20
+ # trying to use a non-restorable strategy with +reuse_access_tokens+.
21
+ def self.allows_restoring_secrets?
22
+ false
23
+ end
24
+ end
25
+ end
26
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Doorkeeper
4
4
  class StaleRecordsCleaner
5
- CLEANER_CLASS = 'StaleRecordsCleaner'.freeze
5
+ CLEANER_CLASS = "StaleRecordsCleaner"
6
6
 
7
7
  def self.for(base_scope)
8
8
  orm_adapter = "doorkeeper/orm/#{Doorkeeper.configuration.orm}".classify
@@ -8,11 +8,11 @@ module Doorkeeper
8
8
  module VERSION
9
9
  # Semantic versioning
10
10
  MAJOR = 5
11
- MINOR = 0
12
- TINY = 3
11
+ MINOR = 1
12
+ TINY = 0
13
13
  PRE = nil
14
14
 
15
15
  # Full version number
16
- STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
16
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
17
17
  end
18
18
  end