doorkeeper 5.0.2 → 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 (214) hide show
  1. checksums.yaml +5 -5
  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 +80 -19
  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 +17 -5
  14. data/app/controllers/doorkeeper/token_info_controller.rb +2 -2
  15. data/app/controllers/doorkeeper/tokens_controller.rb +11 -11
  16. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  17. data/app/validators/redirect_uri_validator.rb +5 -2
  18. data/app/views/doorkeeper/applications/_form.html.erb +6 -0
  19. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  20. data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
  21. data/bin/console +16 -0
  22. data/config/locales/en.yml +1 -0
  23. data/doorkeeper.gemspec +24 -21
  24. data/gemfiles/rails_5_0.gemfile +9 -4
  25. data/gemfiles/rails_5_1.gemfile +9 -4
  26. data/gemfiles/rails_5_2.gemfile +10 -5
  27. data/gemfiles/rails_6_0.gemfile +17 -0
  28. data/gemfiles/rails_master.gemfile +9 -9
  29. data/lib/doorkeeper/config/option.rb +64 -0
  30. data/lib/doorkeeper/config.rb +191 -75
  31. data/lib/doorkeeper/engine.rb +1 -1
  32. data/lib/doorkeeper/grape/authorization_decorator.rb +4 -4
  33. data/lib/doorkeeper/grape/helpers.rb +3 -3
  34. data/lib/doorkeeper/helpers/controller.rb +3 -2
  35. data/lib/doorkeeper/models/access_grant_mixin.rb +20 -3
  36. data/lib/doorkeeper/models/access_token_mixin.rb +63 -19
  37. data/lib/doorkeeper/models/application_mixin.rb +43 -1
  38. data/lib/doorkeeper/models/concerns/expirable.rb +4 -2
  39. data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
  40. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  41. data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
  42. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  43. data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
  44. data/lib/doorkeeper/oauth/authorization/code.rb +2 -2
  45. data/lib/doorkeeper/oauth/authorization/token.rb +12 -7
  46. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
  47. data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -4
  48. data/lib/doorkeeper/oauth/client.rb +1 -1
  49. data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -4
  50. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
  51. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  52. data/lib/doorkeeper/oauth/error_response.rb +10 -6
  53. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  54. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
  55. data/lib/doorkeeper/oauth/helpers/unique_token.rb +13 -1
  56. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +37 -1
  57. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -1
  58. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  59. data/lib/doorkeeper/oauth/pre_authorization.rb +11 -5
  60. data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
  61. data/lib/doorkeeper/oauth/scopes.rb +5 -3
  62. data/lib/doorkeeper/oauth/token.rb +2 -2
  63. data/lib/doorkeeper/oauth/token_introspection.rb +74 -8
  64. data/lib/doorkeeper/oauth/token_response.rb +9 -9
  65. data/lib/doorkeeper/oauth.rb +5 -5
  66. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
  67. data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
  68. data/lib/doorkeeper/orm/active_record/application.rb +26 -7
  69. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
  70. data/lib/doorkeeper/orm/active_record.rb +6 -6
  71. data/lib/doorkeeper/rails/helpers.rb +1 -1
  72. data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
  73. data/lib/doorkeeper/rails/routes.rb +11 -11
  74. data/lib/doorkeeper/rake/db.rake +13 -13
  75. data/lib/doorkeeper/rake.rb +1 -1
  76. data/lib/doorkeeper/request.rb +1 -1
  77. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  78. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  79. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  80. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  81. data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
  82. data/lib/doorkeeper/version.rb +3 -3
  83. data/lib/doorkeeper.rb +69 -60
  84. data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
  85. data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
  86. data/lib/generators/doorkeeper/install_generator.rb +11 -9
  87. data/lib/generators/doorkeeper/migration_generator.rb +9 -9
  88. data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
  89. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
  90. data/lib/generators/doorkeeper/templates/initializer.rb +120 -13
  91. data/lib/generators/doorkeeper/templates/migration.rb.erb +15 -7
  92. data/lib/generators/doorkeeper/views_generator.rb +6 -4
  93. data/spec/controllers/application_metal_controller_spec.rb +24 -10
  94. data/spec/controllers/applications_controller_spec.rb +54 -52
  95. data/spec/controllers/authorizations_controller_spec.rb +139 -145
  96. data/spec/controllers/protected_resources_controller_spec.rb +78 -76
  97. data/spec/controllers/token_info_controller_spec.rb +14 -12
  98. data/spec/controllers/tokens_controller_spec.rb +167 -108
  99. data/spec/dummy/Rakefile +3 -1
  100. data/spec/dummy/app/controllers/application_controller.rb +3 -1
  101. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +2 -0
  102. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
  103. data/spec/dummy/app/controllers/home_controller.rb +5 -3
  104. data/spec/dummy/app/controllers/metal_controller.rb +2 -0
  105. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
  106. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  107. data/spec/dummy/app/models/user.rb +2 -0
  108. data/spec/dummy/config/application.rb +25 -1
  109. data/spec/dummy/config/environments/development.rb +2 -0
  110. data/spec/dummy/config/environments/production.rb +2 -0
  111. data/spec/dummy/config/environments/test.rb +3 -1
  112. data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
  113. data/spec/dummy/config/initializers/doorkeeper.rb +5 -2
  114. data/spec/dummy/config/initializers/secret_token.rb +3 -1
  115. data/spec/dummy/config/initializers/session_store.rb +3 -1
  116. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
  117. data/spec/dummy/config.ru +3 -1
  118. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +17 -10
  119. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
  120. data/spec/dummy/db/schema.rb +1 -1
  121. data/spec/dummy/script/rails +5 -3
  122. data/spec/factories.rb +8 -6
  123. data/spec/generators/application_owner_generator_spec.rb +13 -26
  124. data/spec/generators/confidential_applications_generator_spec.rb +12 -28
  125. data/spec/generators/install_generator_spec.rb +17 -15
  126. data/spec/generators/migration_generator_spec.rb +13 -26
  127. data/spec/generators/pkce_generator_spec.rb +11 -26
  128. data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
  129. data/spec/generators/templates/routes.rb +2 -0
  130. data/spec/generators/views_generator_spec.rb +14 -12
  131. data/spec/grape/grape_integration_spec.rb +34 -32
  132. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
  133. data/spec/lib/config_spec.rb +268 -99
  134. data/spec/lib/doorkeeper_spec.rb +3 -1
  135. data/spec/lib/models/expirable_spec.rb +22 -8
  136. data/spec/lib/models/reusable_spec.rb +40 -0
  137. data/spec/lib/models/revocable_spec.rb +8 -6
  138. data/spec/lib/models/scopes_spec.rb +27 -13
  139. data/spec/lib/models/secret_storable_spec.rb +135 -0
  140. data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
  141. data/spec/lib/oauth/authorization_code_request_spec.rb +34 -11
  142. data/spec/lib/oauth/base_request_spec.rb +20 -8
  143. data/spec/lib/oauth/base_response_spec.rb +3 -1
  144. data/spec/lib/oauth/client/credentials_spec.rb +24 -22
  145. data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
  146. data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
  147. data/spec/lib/oauth/client_credentials/validation_spec.rb +20 -15
  148. data/spec/lib/oauth/client_credentials_integration_spec.rb +7 -5
  149. data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
  150. data/spec/lib/oauth/client_spec.rb +15 -13
  151. data/spec/lib/oauth/code_request_spec.rb +8 -6
  152. data/spec/lib/oauth/code_response_spec.rb +9 -7
  153. data/spec/lib/oauth/error_response_spec.rb +19 -11
  154. data/spec/lib/oauth/error_spec.rb +4 -2
  155. data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
  156. data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
  157. data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
  158. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -95
  159. data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
  160. data/spec/lib/oauth/password_access_token_request_spec.rb +79 -30
  161. data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
  162. data/spec/lib/oauth/refresh_token_request_spec.rb +36 -33
  163. data/spec/lib/oauth/scopes_spec.rb +63 -61
  164. data/spec/lib/oauth/token_request_spec.rb +79 -24
  165. data/spec/lib/oauth/token_response_spec.rb +40 -38
  166. data/spec/lib/oauth/token_spec.rb +60 -44
  167. data/spec/lib/request/strategy_spec.rb +3 -1
  168. data/spec/lib/secret_storing/base_spec.rb +60 -0
  169. data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
  170. data/spec/lib/secret_storing/plain_spec.rb +44 -0
  171. data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
  172. data/spec/lib/server_spec.rb +16 -14
  173. data/spec/lib/stale_records_cleaner_spec.rb +17 -17
  174. data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
  175. data/spec/models/doorkeeper/access_token_spec.rb +198 -73
  176. data/spec/models/doorkeeper/application_spec.rb +142 -45
  177. data/spec/requests/applications/applications_request_spec.rb +98 -66
  178. data/spec/requests/applications/authorized_applications_spec.rb +20 -18
  179. data/spec/requests/endpoints/authorization_spec.rb +25 -23
  180. data/spec/requests/endpoints/token_spec.rb +38 -36
  181. data/spec/requests/flows/authorization_code_errors_spec.rb +26 -24
  182. data/spec/requests/flows/authorization_code_spec.rb +193 -151
  183. data/spec/requests/flows/client_credentials_spec.rb +54 -52
  184. data/spec/requests/flows/implicit_grant_errors_spec.rb +10 -8
  185. data/spec/requests/flows/implicit_grant_spec.rb +27 -25
  186. data/spec/requests/flows/password_spec.rb +59 -55
  187. data/spec/requests/flows/refresh_token_spec.rb +45 -43
  188. data/spec/requests/flows/revoke_token_spec.rb +40 -54
  189. data/spec/requests/flows/skip_authorization_spec.rb +23 -21
  190. data/spec/requests/protected_resources/metal_spec.rb +7 -5
  191. data/spec/requests/protected_resources/private_api_spec.rb +35 -33
  192. data/spec/routing/custom_controller_routes_spec.rb +71 -65
  193. data/spec/routing/default_routes_spec.rb +22 -20
  194. data/spec/routing/scoped_routes_spec.rb +20 -18
  195. data/spec/spec_helper.rb +15 -13
  196. data/spec/spec_helper_integration.rb +3 -1
  197. data/spec/support/dependencies/factory_bot.rb +3 -1
  198. data/spec/support/doorkeeper_rspec.rb +3 -1
  199. data/spec/support/helpers/access_token_request_helper.rb +3 -1
  200. data/spec/support/helpers/authorization_request_helper.rb +4 -2
  201. data/spec/support/helpers/config_helper.rb +2 -0
  202. data/spec/support/helpers/model_helper.rb +3 -1
  203. data/spec/support/helpers/request_spec_helper.rb +5 -3
  204. data/spec/support/helpers/url_helper.rb +9 -7
  205. data/spec/support/http_method_shim.rb +4 -9
  206. data/spec/support/orm/active_record.rb +3 -1
  207. data/spec/support/shared/controllers_shared_context.rb +18 -16
  208. data/spec/support/shared/hashing_shared_context.rb +36 -0
  209. data/spec/support/shared/models_shared_examples.rb +12 -10
  210. data/spec/validators/redirect_uri_validator_spec.rb +74 -45
  211. data/spec/version/version_spec.rb +7 -5
  212. metadata +61 -28
  213. data/gemfiles/rails_4_2.gemfile +0 -13
  214. data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
@@ -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 = 2
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
data/lib/doorkeeper.rb CHANGED
@@ -1,75 +1,84 @@
1
- require 'doorkeeper/version'
2
- require 'doorkeeper/engine'
3
- require 'doorkeeper/config'
1
+ # frozen_string_literal: true
4
2
 
5
- require 'doorkeeper/request/strategy'
6
- require 'doorkeeper/request/authorization_code'
7
- require 'doorkeeper/request/client_credentials'
8
- require 'doorkeeper/request/code'
9
- require 'doorkeeper/request/password'
10
- require 'doorkeeper/request/refresh_token'
11
- require 'doorkeeper/request/token'
3
+ require "doorkeeper/version"
4
+ require "doorkeeper/engine"
5
+ require "doorkeeper/config"
12
6
 
13
- require 'doorkeeper/errors'
14
- require 'doorkeeper/server'
15
- require 'doorkeeper/request'
16
- require 'doorkeeper/validations'
7
+ require "doorkeeper/request/strategy"
8
+ require "doorkeeper/request/authorization_code"
9
+ require "doorkeeper/request/client_credentials"
10
+ require "doorkeeper/request/code"
11
+ require "doorkeeper/request/password"
12
+ require "doorkeeper/request/refresh_token"
13
+ require "doorkeeper/request/token"
17
14
 
18
- require 'doorkeeper/oauth/authorization/code'
19
- require 'doorkeeper/oauth/authorization/context'
20
- require 'doorkeeper/oauth/authorization/token'
21
- require 'doorkeeper/oauth/authorization/uri_builder'
22
- require 'doorkeeper/oauth/helpers/scope_checker'
23
- require 'doorkeeper/oauth/helpers/uri_checker'
24
- require 'doorkeeper/oauth/helpers/unique_token'
15
+ require "doorkeeper/errors"
16
+ require "doorkeeper/server"
17
+ require "doorkeeper/request"
18
+ require "doorkeeper/validations"
25
19
 
26
- require 'doorkeeper/oauth'
27
- require 'doorkeeper/oauth/scopes'
28
- require 'doorkeeper/oauth/error'
29
- require 'doorkeeper/oauth/base_response'
30
- require 'doorkeeper/oauth/code_response'
31
- require 'doorkeeper/oauth/token_response'
32
- require 'doorkeeper/oauth/error_response'
33
- require 'doorkeeper/oauth/pre_authorization'
34
- require 'doorkeeper/oauth/base_request'
35
- require 'doorkeeper/oauth/authorization_code_request'
36
- require 'doorkeeper/oauth/refresh_token_request'
37
- require 'doorkeeper/oauth/password_access_token_request'
20
+ require "doorkeeper/oauth/authorization/code"
21
+ require "doorkeeper/oauth/authorization/context"
22
+ require "doorkeeper/oauth/authorization/token"
23
+ require "doorkeeper/oauth/authorization/uri_builder"
24
+ require "doorkeeper/oauth/helpers/scope_checker"
25
+ require "doorkeeper/oauth/helpers/uri_checker"
26
+ require "doorkeeper/oauth/helpers/unique_token"
38
27
 
39
- require 'doorkeeper/oauth/client_credentials/validation'
40
- require 'doorkeeper/oauth/client_credentials/creator'
41
- require 'doorkeeper/oauth/client_credentials/issuer'
42
- require 'doorkeeper/oauth/client_credentials/validation'
43
- require 'doorkeeper/oauth/client/credentials'
28
+ require "doorkeeper/oauth"
29
+ require "doorkeeper/oauth/scopes"
30
+ require "doorkeeper/oauth/error"
31
+ require "doorkeeper/oauth/base_response"
32
+ require "doorkeeper/oauth/code_response"
33
+ require "doorkeeper/oauth/token_response"
34
+ require "doorkeeper/oauth/error_response"
35
+ require "doorkeeper/oauth/pre_authorization"
36
+ require "doorkeeper/oauth/base_request"
37
+ require "doorkeeper/oauth/authorization_code_request"
38
+ require "doorkeeper/oauth/refresh_token_request"
39
+ require "doorkeeper/oauth/password_access_token_request"
44
40
 
45
- require 'doorkeeper/oauth/client_credentials_request'
46
- require 'doorkeeper/oauth/code_request'
47
- require 'doorkeeper/oauth/token_request'
48
- require 'doorkeeper/oauth/client'
49
- require 'doorkeeper/oauth/token'
50
- require 'doorkeeper/oauth/token_introspection'
51
- require 'doorkeeper/oauth/invalid_token_response'
52
- require 'doorkeeper/oauth/forbidden_token_response'
41
+ require "doorkeeper/oauth/client_credentials/validation"
42
+ require "doorkeeper/oauth/client_credentials/creator"
43
+ require "doorkeeper/oauth/client_credentials/issuer"
44
+ require "doorkeeper/oauth/client_credentials/validation"
45
+ require "doorkeeper/oauth/client/credentials"
53
46
 
54
- require 'doorkeeper/models/concerns/orderable'
55
- require 'doorkeeper/models/concerns/scopes'
56
- require 'doorkeeper/models/concerns/expirable'
57
- require 'doorkeeper/models/concerns/revocable'
58
- require 'doorkeeper/models/concerns/accessible'
47
+ require "doorkeeper/oauth/client_credentials_request"
48
+ require "doorkeeper/oauth/code_request"
49
+ require "doorkeeper/oauth/token_request"
50
+ require "doorkeeper/oauth/client"
51
+ require "doorkeeper/oauth/token"
52
+ require "doorkeeper/oauth/token_introspection"
53
+ require "doorkeeper/oauth/invalid_token_response"
54
+ require "doorkeeper/oauth/forbidden_token_response"
59
55
 
60
- require 'doorkeeper/models/access_grant_mixin'
61
- require 'doorkeeper/models/access_token_mixin'
62
- require 'doorkeeper/models/application_mixin'
56
+ require "doorkeeper/secret_storing/base"
57
+ require "doorkeeper/secret_storing/plain"
58
+ require "doorkeeper/secret_storing/sha256_hash"
59
+ require "doorkeeper/secret_storing/bcrypt"
63
60
 
64
- require 'doorkeeper/helpers/controller'
61
+ require "doorkeeper/models/concerns/orderable"
62
+ require "doorkeeper/models/concerns/scopes"
63
+ require "doorkeeper/models/concerns/expirable"
64
+ require "doorkeeper/models/concerns/reusable"
65
+ require "doorkeeper/models/concerns/revocable"
66
+ require "doorkeeper/models/concerns/accessible"
67
+ require "doorkeeper/models/concerns/secret_storable"
65
68
 
66
- require 'doorkeeper/rails/routes'
67
- require 'doorkeeper/rails/helpers'
69
+ require "doorkeeper/models/access_grant_mixin"
70
+ require "doorkeeper/models/access_token_mixin"
71
+ require "doorkeeper/models/application_mixin"
68
72
 
69
- require 'doorkeeper/rake'
70
- require 'doorkeeper/stale_records_cleaner'
73
+ require "doorkeeper/helpers/controller"
71
74
 
72
- require 'doorkeeper/orm/active_record'
75
+ require "doorkeeper/rails/routes"
76
+ require "doorkeeper/rails/helpers"
77
+
78
+ require "doorkeeper/rake"
79
+ require "doorkeeper/stale_records_cleaner"
80
+
81
+ require "doorkeeper/orm/active_record"
73
82
 
74
83
  module Doorkeeper
75
84
  def self.authenticate(request, methods = Doorkeeper.configuration.access_token_methods)
@@ -1,18 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails/generators'
4
- require 'rails/generators/active_record'
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
5
 
6
6
  module Doorkeeper
7
+ # Generates migration to add reference to owner of the
8
+ # Doorkeeper application.
9
+ #
7
10
  class ApplicationOwnerGenerator < ::Rails::Generators::Base
8
11
  include ::Rails::Generators::Migration
9
- source_root File.expand_path('templates', __dir__)
10
- desc 'Provide support for client application ownership.'
12
+ source_root File.expand_path("templates", __dir__)
13
+ desc "Provide support for client application ownership."
11
14
 
12
15
  def application_owner
13
16
  migration_template(
14
- 'add_owner_to_application_migration.rb.erb',
15
- 'db/migrate/add_owner_to_application.rb',
17
+ "add_owner_to_application_migration.rb.erb",
18
+ "db/migrate/add_owner_to_application.rb",
16
19
  migration_version: migration_version
17
20
  )
18
21
  end
@@ -24,9 +27,7 @@ module Doorkeeper
24
27
  private
25
28
 
26
29
  def migration_version
27
- if ActiveRecord::VERSION::MAJOR >= 5
28
- "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
29
- end
30
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
30
31
  end
31
32
  end
32
33
  end