doorkeeper 4.4.3 → 5.0.0

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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitlab-ci.yml +16 -0
  4. data/.travis.yml +2 -0
  5. data/Appraisals +2 -2
  6. data/Gemfile +1 -1
  7. data/NEWS.md +61 -8
  8. data/README.md +92 -9
  9. data/Rakefile +6 -0
  10. data/UPGRADE.md +2 -0
  11. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  12. data/app/controllers/doorkeeper/application_controller.rb +4 -3
  13. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
  14. data/app/controllers/doorkeeper/applications_controller.rb +42 -22
  15. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  16. data/app/controllers/doorkeeper/authorized_applications_controller.rb +19 -2
  17. data/app/controllers/doorkeeper/tokens_controller.rb +2 -6
  18. data/app/helpers/doorkeeper/dashboard_helper.rb +7 -7
  19. data/app/validators/redirect_uri_validator.rb +3 -2
  20. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  21. data/app/views/doorkeeper/applications/_form.html.erb +25 -24
  22. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  23. data/app/views/doorkeeper/applications/index.html.erb +17 -7
  24. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  25. data/app/views/doorkeeper/applications/show.html.erb +6 -6
  26. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  27. data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
  28. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  29. data/config/locales/en.yml +10 -1
  30. data/doorkeeper.gemspec +18 -20
  31. data/gemfiles/rails_5_2.gemfile +1 -1
  32. data/gemfiles/rails_master.gemfile +4 -1
  33. data/lib/doorkeeper/config.rb +75 -39
  34. data/lib/doorkeeper/engine.rb +4 -0
  35. data/lib/doorkeeper/errors.rb +2 -5
  36. data/lib/doorkeeper/grape/helpers.rb +1 -1
  37. data/lib/doorkeeper/helpers/controller.rb +7 -2
  38. data/lib/doorkeeper/models/access_grant_mixin.rb +71 -0
  39. data/lib/doorkeeper/models/access_token_mixin.rb +39 -22
  40. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  41. data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
  42. data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
  43. data/lib/doorkeeper/oauth/authorization/token.rb +36 -14
  44. data/lib/doorkeeper/oauth/authorization_code_request.rb +27 -2
  45. data/lib/doorkeeper/oauth/base_request.rb +20 -9
  46. data/lib/doorkeeper/oauth/client/credentials.rb +1 -1
  47. data/lib/doorkeeper/oauth/client.rb +0 -2
  48. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
  49. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -3
  50. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -6
  51. data/lib/doorkeeper/oauth/client_credentials_request.rb +0 -4
  52. data/lib/doorkeeper/oauth/error_response.rb +11 -3
  53. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
  54. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -4
  55. data/lib/doorkeeper/oauth/pre_authorization.rb +41 -11
  56. data/lib/doorkeeper/oauth/refresh_token_request.rb +6 -1
  57. data/lib/doorkeeper/oauth/scopes.rb +1 -1
  58. data/lib/doorkeeper/oauth/token.rb +5 -2
  59. data/lib/doorkeeper/oauth/token_introspection.rb +2 -2
  60. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  61. data/lib/doorkeeper/oauth.rb +13 -0
  62. data/lib/doorkeeper/orm/active_record/application.rb +22 -14
  63. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  64. data/lib/doorkeeper/orm/active_record.rb +2 -0
  65. data/lib/doorkeeper/rails/helpers.rb +2 -4
  66. data/lib/doorkeeper/rails/routes.rb +14 -6
  67. data/lib/doorkeeper/rake/db.rake +40 -0
  68. data/lib/doorkeeper/rake/setup.rake +6 -0
  69. data/lib/doorkeeper/rake.rb +14 -0
  70. data/lib/doorkeeper/request/authorization_code.rb +0 -2
  71. data/lib/doorkeeper/request/client_credentials.rb +0 -2
  72. data/lib/doorkeeper/request/code.rb +0 -2
  73. data/lib/doorkeeper/request/password.rb +0 -2
  74. data/lib/doorkeeper/request/refresh_token.rb +0 -2
  75. data/lib/doorkeeper/request/token.rb +0 -2
  76. data/lib/doorkeeper/request.rb +28 -35
  77. data/lib/doorkeeper/version.rb +5 -25
  78. data/lib/doorkeeper.rb +19 -17
  79. data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
  80. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  81. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  82. data/lib/generators/doorkeeper/migration_generator.rb +23 -18
  83. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  84. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
  85. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  86. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  87. data/lib/generators/doorkeeper/templates/initializer.rb +76 -11
  88. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  89. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  90. data/spec/controllers/applications_controller_spec.rb +126 -13
  91. data/spec/controllers/authorizations_controller_spec.rb +277 -47
  92. data/spec/controllers/protected_resources_controller_spec.rb +16 -16
  93. data/spec/controllers/token_info_controller_spec.rb +4 -12
  94. data/spec/controllers/tokens_controller_spec.rb +13 -15
  95. data/spec/dummy/app/assets/config/manifest.js +2 -0
  96. data/spec/dummy/config/environments/test.rb +4 -5
  97. data/spec/dummy/config/initializers/doorkeeper.rb +10 -5
  98. data/spec/dummy/config/initializers/new_framework_defaults.rb +4 -0
  99. data/spec/dummy/config/routes.rb +3 -42
  100. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  101. data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
  102. data/spec/dummy/db/schema.rb +36 -36
  103. data/spec/generators/application_owner_generator_spec.rb +1 -1
  104. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  105. data/spec/generators/install_generator_spec.rb +1 -1
  106. data/spec/generators/migration_generator_spec.rb +1 -1
  107. data/spec/generators/pkce_generator_spec.rb +43 -0
  108. data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
  109. data/spec/generators/views_generator_spec.rb +1 -1
  110. data/spec/grape/grape_integration_spec.rb +1 -1
  111. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  112. data/spec/lib/config_spec.rb +80 -31
  113. data/spec/lib/doorkeeper_spec.rb +1 -126
  114. data/spec/lib/models/expirable_spec.rb +0 -3
  115. data/spec/lib/models/revocable_spec.rb +0 -2
  116. data/spec/lib/models/scopes_spec.rb +0 -4
  117. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  118. data/spec/lib/oauth/authorization_code_request_spec.rb +9 -2
  119. data/spec/lib/oauth/base_request_spec.rb +40 -2
  120. data/spec/lib/oauth/base_response_spec.rb +1 -1
  121. data/spec/lib/oauth/client/credentials_spec.rb +1 -3
  122. data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
  123. data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
  124. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
  125. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  126. data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
  127. data/spec/lib/oauth/client_spec.rb +0 -3
  128. data/spec/lib/oauth/code_request_spec.rb +4 -2
  129. data/spec/lib/oauth/error_response_spec.rb +0 -3
  130. data/spec/lib/oauth/error_spec.rb +0 -2
  131. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  132. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
  133. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  134. data/spec/lib/oauth/helpers/uri_checker_spec.rb +5 -7
  135. data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
  136. data/spec/lib/oauth/password_access_token_request_spec.rb +37 -2
  137. data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
  138. data/spec/lib/oauth/refresh_token_request_spec.rb +11 -7
  139. data/spec/lib/oauth/scopes_spec.rb +0 -3
  140. data/spec/lib/oauth/token_request_spec.rb +4 -5
  141. data/spec/lib/oauth/token_response_spec.rb +0 -1
  142. data/spec/lib/oauth/token_spec.rb +37 -14
  143. data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
  144. data/spec/lib/request/strategy_spec.rb +0 -1
  145. data/spec/lib/server_spec.rb +1 -1
  146. data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
  147. data/spec/models/doorkeeper/access_token_spec.rb +66 -22
  148. data/spec/models/doorkeeper/application_spec.rb +14 -47
  149. data/spec/requests/applications/applications_request_spec.rb +134 -1
  150. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  151. data/spec/requests/endpoints/authorization_spec.rb +1 -1
  152. data/spec/requests/endpoints/token_spec.rb +7 -5
  153. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
  154. data/spec/requests/flows/authorization_code_spec.rb +197 -1
  155. data/spec/requests/flows/client_credentials_spec.rb +46 -6
  156. data/spec/requests/flows/implicit_grant_errors_spec.rb +1 -1
  157. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  158. data/spec/requests/flows/password_spec.rb +56 -2
  159. data/spec/requests/flows/refresh_token_spec.rb +2 -2
  160. data/spec/requests/flows/revoke_token_spec.rb +11 -11
  161. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  162. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  163. data/spec/requests/protected_resources/private_api_spec.rb +1 -1
  164. data/spec/routing/custom_controller_routes_spec.rb +59 -7
  165. data/spec/routing/default_routes_spec.rb +2 -2
  166. data/spec/routing/scoped_routes_spec.rb +16 -2
  167. data/spec/spec_helper.rb +54 -3
  168. data/spec/spec_helper_integration.rb +2 -74
  169. data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
  170. data/spec/support/doorkeeper_rspec.rb +19 -0
  171. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  172. data/spec/support/helpers/request_spec_helper.rb +10 -2
  173. data/spec/support/helpers/url_helper.rb +7 -3
  174. data/spec/support/http_method_shim.rb +12 -16
  175. data/spec/validators/redirect_uri_validator_spec.rb +7 -1
  176. data/spec/version/version_spec.rb +3 -3
  177. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  178. metadata +37 -33
  179. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
  180. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
  181. data/spec/controllers/application_metal_controller.rb +0 -10
@@ -16,6 +16,7 @@ module Doorkeeper
16
16
  @client = client
17
17
  @parameters = parameters
18
18
  @original_scopes = parameters[:scope]
19
+ @grant_type = Doorkeeper::OAuth::PASSWORD
19
20
  end
20
21
 
21
22
  private
@@ -26,16 +27,18 @@ module Doorkeeper
26
27
  end
27
28
 
28
29
  def validate_scopes
29
- return true unless @original_scopes.present?
30
- ScopeChecker.valid? @original_scopes, server.scopes, client.try(:scopes)
30
+ client_scopes = client.try(:scopes)
31
+ return true if scopes.blank?
32
+
33
+ ScopeChecker.valid?(scopes.to_s, server.scopes, client_scopes)
31
34
  end
32
35
 
33
36
  def validate_resource_owner
34
- !!resource_owner
37
+ !resource_owner.nil?
35
38
  end
36
39
 
37
40
  def validate_client
38
- !parameters[:client_id] || !!client
41
+ !parameters[:client_id] || !client.nil?
39
42
  end
40
43
  end
41
44
  end
@@ -7,17 +7,21 @@ module Doorkeeper
7
7
  validate :client, error: :invalid_client
8
8
  validate :scopes, error: :invalid_scope
9
9
  validate :redirect_uri, error: :invalid_redirect_uri
10
+ validate :code_challenge_method, error: :invalid_code_challenge_method
10
11
 
11
- attr_accessor :server, :client, :response_type, :redirect_uri, :state
12
+ attr_accessor :server, :client, :response_type, :redirect_uri, :state,
13
+ :code_challenge, :code_challenge_method
12
14
  attr_writer :scope
13
15
 
14
16
  def initialize(server, client, attrs = {})
15
- @server = server
16
- @client = client
17
- @response_type = attrs[:response_type]
18
- @redirect_uri = attrs[:redirect_uri]
19
- @scope = attrs[:scope]
20
- @state = attrs[:state]
17
+ @server = server
18
+ @client = client
19
+ @response_type = attrs[:response_type]
20
+ @redirect_uri = attrs[:redirect_uri]
21
+ @scope = attrs[:scope]
22
+ @state = attrs[:state]
23
+ @code_challenge = attrs[:code_challenge]
24
+ @code_challenge_method = attrs[:code_challenge_method]
21
25
  end
22
26
 
23
27
  def authorizable?
@@ -29,15 +33,36 @@ module Doorkeeper
29
33
  end
30
34
 
31
35
  def scope
32
- @scope.presence || server.default_scopes.to_s
36
+ @scope.presence || build_scopes
33
37
  end
34
38
 
35
39
  def error_response
36
40
  OAuth::ErrorResponse.from_request(self)
37
41
  end
38
42
 
43
+ def as_json(_options)
44
+ {
45
+ client_id: client.uid,
46
+ redirect_uri: redirect_uri,
47
+ state: state,
48
+ response_type: response_type,
49
+ scope: scope,
50
+ client_name: client.name,
51
+ status: I18n.t('doorkeeper.pre_authorization.status')
52
+ }
53
+ end
54
+
39
55
  private
40
56
 
57
+ def build_scopes
58
+ client_scopes = client.application.scopes
59
+ if client_scopes.blank?
60
+ server.default_scopes.to_s
61
+ else
62
+ (server.default_scopes & client_scopes).to_s
63
+ end
64
+ end
65
+
41
66
  def validate_response_type
42
67
  server.authorization_response_types.include? response_type
43
68
  end
@@ -47,7 +72,8 @@ module Doorkeeper
47
72
  end
48
73
 
49
74
  def validate_scopes
50
- return true unless scope.present?
75
+ return true if scope.blank?
76
+
51
77
  Helpers::ScopeChecker.valid?(
52
78
  scope,
53
79
  server.scopes,
@@ -55,14 +81,18 @@ module Doorkeeper
55
81
  )
56
82
  end
57
83
 
58
- # TODO: test uri should be matched against the client's one
59
84
  def validate_redirect_uri
60
85
  return false if redirect_uri.blank?
61
86
 
62
87
  Helpers::URIChecker.valid_for_authorization?(
63
- redirect_uri, client.redirect_uri
88
+ redirect_uri,
89
+ client.redirect_uri
64
90
  )
65
91
  end
92
+
93
+ def validate_code_challenge_method
94
+ !code_challenge.present? || (code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
95
+ end
66
96
  end
67
97
  end
68
98
  end
@@ -65,7 +65,12 @@ module Doorkeeper
65
65
  end
66
66
 
67
67
  def access_token_expires_in
68
- Authorization::Token.access_token_expires_in(server, client)
68
+ context = Authorization::Token.build_context(
69
+ client,
70
+ Doorkeeper::OAuth::REFRESH_TOKEN,
71
+ scopes
72
+ )
73
+ Authorization::Token.access_token_expires_in(server, context)
69
74
  end
70
75
 
71
76
  def validate_token_presence
@@ -41,7 +41,7 @@ module Doorkeeper
41
41
  end
42
42
 
43
43
  def has_scopes?(scopes)
44
- scopes.all? { |s| exists?(s) }
44
+ scopes.all? { |scope| exists?(scope) }
45
45
  end
46
46
 
47
47
  def +(other)
@@ -3,7 +3,7 @@ module Doorkeeper
3
3
  class Token
4
4
  class << self
5
5
  def from_request(request, *methods)
6
- methods.inject(nil) do |credentials, method|
6
+ methods.inject(nil) do |_, method|
7
7
  method = self.method(method) if method.is_a?(Symbol)
8
8
  credentials = method.call(request)
9
9
  break credentials unless credentials.blank?
@@ -13,7 +13,10 @@ module Doorkeeper
13
13
  def authenticate(request, *methods)
14
14
  if (token = from_request(request, *methods))
15
15
  access_token = AccessToken.by_token(token)
16
- access_token.revoke_previous_refresh_token! if access_token
16
+ refresh_token_enabled = Doorkeeper.configuration.refresh_token_enabled?
17
+ if access_token.present? && refresh_token_enabled
18
+ access_token.revoke_previous_refresh_token!
19
+ end
17
20
  access_token
18
21
  end
19
22
  end
@@ -47,12 +47,12 @@ module Doorkeeper
47
47
 
48
48
  # Client Authentication
49
49
  def authorized_client
50
- @_authorized_client ||= server.credentials && server.client
50
+ @authorized_client ||= server.credentials && server.client
51
51
  end
52
52
 
53
53
  # Bearer Token Authentication
54
54
  def authorized_token
55
- @_authorized_token ||=
55
+ @authorized_token ||=
56
56
  OAuth::Token.authenticate(server.context.request, :from_bearer_authorization)
57
57
  end
58
58
 
@@ -23,9 +23,11 @@ module Doorkeeper
23
23
  end
24
24
 
25
25
  def headers
26
- { 'Cache-Control' => 'no-store',
26
+ {
27
+ 'Cache-Control' => 'no-store',
27
28
  'Pragma' => 'no-cache',
28
- 'Content-Type' => 'application/json; charset=utf-8' }
29
+ 'Content-Type' => 'application/json; charset=utf-8'
30
+ }
29
31
  end
30
32
  end
31
33
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ GRANT_TYPES = [
6
+ AUTHORIZATION_CODE = 'authorization_code'.freeze,
7
+ IMPLICIT = 'implicit'.freeze,
8
+ PASSWORD = 'password'.freeze,
9
+ CLIENT_CREDENTIALS = 'client_credentials'.freeze,
10
+ REFRESH_TOKEN = 'refresh_token'.freeze
11
+ ].freeze
12
+ end
13
+ end
@@ -13,6 +13,8 @@ module Doorkeeper
13
13
  validates :redirect_uri, redirect_uri: true
14
14
  validates :confidential, inclusion: { in: [true, false] }
15
15
 
16
+ validate :scopes_match_configured, if: :enforce_scopes?
17
+
16
18
  before_validation :generate_uid, :generate_secret, on: :create
17
19
 
18
20
  has_many :authorized_tokens, -> { where(revoked_at: nil) }, class_name: 'AccessToken'
@@ -32,20 +34,15 @@ module Doorkeeper
32
34
  where(id: resource_access_tokens.select(:application_id).distinct)
33
35
  end
34
36
 
35
- # Fallback to existing, default behaviour of assuming all apps to be
36
- # confidential if the migration hasn't been run
37
- def confidential
38
- return super if self.class.supports_confidentiality?
39
- ActiveSupport::Deprecation.warn 'You are susceptible to security bug ' \
40
- 'CVE-2018-1000211. Please follow instructions outlined in ' \
41
- 'Doorkeeper::CVE_2018_1000211_WARNING'
42
- true
43
- end
44
-
45
- alias_method :confidential?, :confidential
46
-
47
- def self.supports_confidentiality?
48
- column_names.include?('confidential')
37
+ # Revokes AccessToken and AccessGrant records that have not been revoked and
38
+ # associated with the specific Application and Resource Owner.
39
+ #
40
+ # @param resource_owner [ActiveRecord::Base]
41
+ # instance of the Resource Owner model
42
+ #
43
+ def self.revoke_tokens_and_grants_for(id, resource_owner)
44
+ AccessToken.revoke_all_for(id, resource_owner)
45
+ AccessGrant.revoke_all_for(id, resource_owner)
49
46
  end
50
47
 
51
48
  private
@@ -57,5 +54,16 @@ module Doorkeeper
57
54
  def generate_secret
58
55
  self.secret = UniqueToken.generate if secret.blank?
59
56
  end
57
+
58
+ def scopes_match_configured
59
+ if scopes.present? &&
60
+ !ScopeChecker.valid?(scopes.to_s, Doorkeeper.configuration.scopes)
61
+ errors.add(:scopes, :not_match_configured)
62
+ end
63
+ end
64
+
65
+ def enforce_scopes?
66
+ Doorkeeper.configuration.enforce_configured_scopes?
67
+ end
60
68
  end
61
69
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Orm
5
+ module ActiveRecord
6
+ class StaleRecordsCleaner
7
+ def initialize(base_scope)
8
+ @base_scope = base_scope
9
+ end
10
+
11
+ def clean_revoked
12
+ table = @base_scope.arel_table
13
+ @base_scope.where.not(revoked_at: nil)
14
+ .where(table[:revoked_at].lt(Time.current))
15
+ .delete_all
16
+ end
17
+
18
+ def clean_expired(ttl)
19
+ table = @base_scope.arel_table
20
+ @base_scope.where(table[:created_at].lt(Time.current - ttl))
21
+ .delete_all
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,7 @@
1
1
  require 'active_support/lazy_load_hooks'
2
2
 
3
+ require 'doorkeeper/orm/active_record/stale_records_cleaner'
4
+
3
5
  module Doorkeeper
4
6
  module Orm
5
7
  module ActiveRecord
@@ -4,9 +4,7 @@ module Doorkeeper
4
4
  def doorkeeper_authorize!(*scopes)
5
5
  @_doorkeeper_scopes = scopes.presence || Doorkeeper.configuration.default_scopes
6
6
 
7
- unless valid_doorkeeper_token?
8
- doorkeeper_render_error
9
- end
7
+ doorkeeper_render_error unless valid_doorkeeper_token?
10
8
  end
11
9
 
12
10
  def doorkeeper_unauthorized_render_options(**); end
@@ -68,7 +66,7 @@ module Doorkeeper
68
66
  end
69
67
 
70
68
  def doorkeeper_token
71
- @_doorkeeper_token ||= OAuth::Token.authenticate(
69
+ @doorkeeper_token ||= OAuth::Token.authenticate(
72
70
  request,
73
71
  *Doorkeeper.configuration.access_token_methods
74
72
  )
@@ -4,6 +4,10 @@ require 'doorkeeper/rails/routes/mapper'
4
4
  module Doorkeeper
5
5
  module Rails
6
6
  class Routes # :nodoc:
7
+ mattr_reader :mapping do
8
+ {}
9
+ end
10
+
7
11
  module Helper
8
12
  def use_doorkeeper(options = {}, &block)
9
13
  Doorkeeper::Rails::Routes.new(self, &block).generate_routes!(options)
@@ -19,6 +23,10 @@ module Doorkeeper
19
23
  def initialize(routes, &block)
20
24
  @routes = routes
21
25
  @mapping = Mapper.new.map(&block)
26
+
27
+ if Doorkeeper.configuration.api_only
28
+ @mapping.skips.push(:applications, :authorized_applications)
29
+ end
22
30
  end
23
31
 
24
32
  def generate_routes!(options)
@@ -36,7 +44,11 @@ module Doorkeeper
36
44
  private
37
45
 
38
46
  def map_route(name, method)
39
- send(method, @mapping[name]) unless @mapping.skipped?(name)
47
+ return if @mapping.skipped?(name)
48
+
49
+ send(method, @mapping[name])
50
+
51
+ mapping[name] = @mapping[name]
40
52
  end
41
53
 
42
54
  def authorization_routes(mapping)
@@ -47,7 +59,7 @@ module Doorkeeper
47
59
  as: mapping[:as],
48
60
  controller: mapping[:controllers]
49
61
  ) do
50
- routes.get native_authorization_code_route, action: :show, on: :member
62
+ routes.get '/native', action: :show, on: :member
51
63
  routes.get '/', action: :new, on: :member
52
64
  end
53
65
  end
@@ -85,10 +97,6 @@ module Doorkeeper
85
97
  def authorized_applications_routes(mapping)
86
98
  routes.resources :authorized_applications, only: %i[index destroy], controller: mapping[:controllers]
87
99
  end
88
-
89
- def native_authorization_code_route
90
- Doorkeeper.configuration.native_authorization_code_route
91
- end
92
100
  end
93
101
  end
94
102
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :doorkeeper do
4
+ namespace :db do
5
+ desc 'Removes stale data from doorkeeper related database tables'
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'
11
+ ]
12
+
13
+ namespace :cleanup do
14
+ desc 'Removes stale access tokens'
15
+ task revoked_tokens: 'doorkeeper:setup' do
16
+ cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(Doorkeeper::AccessToken)
17
+ cleaner.clean_revoked
18
+ end
19
+
20
+ desc 'Removes expired (TTL passed) access tokens'
21
+ task expired_tokens: 'doorkeeper:setup' do
22
+ expirable_tokens = Doorkeeper::AccessToken.where(refresh_token: nil)
23
+ cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(expirable_tokens)
24
+ cleaner.clean_expired(Doorkeeper.configuration.access_token_expires_in)
25
+ end
26
+
27
+ desc 'Removes stale access grants'
28
+ task revoked_grants: 'doorkeeper:setup' do
29
+ cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
30
+ cleaner.clean_revoked
31
+ end
32
+
33
+ desc 'Removes expired (TTL passed) access grants'
34
+ task expired_grants: 'doorkeeper:setup' do
35
+ cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
36
+ cleaner.clean_expired(Doorkeeper.configuration.authorization_code_expires_in)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :doorkeeper do
4
+ task setup: :environment do
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Rake
5
+ class << self
6
+ def load_tasks
7
+ glob = File.join(File.absolute_path(__dir__), 'rake', '*.rake')
8
+ Dir[glob].each do |rake_file|
9
+ load rake_file
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class AuthorizationCode < Strategy
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class ClientCredentials < Strategy
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class Code < Strategy
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class Password < Strategy
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class RefreshToken < Strategy
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class Token < Strategy
@@ -1,46 +1,39 @@
1
- require 'doorkeeper/request/authorization_code'
2
- require 'doorkeeper/request/client_credentials'
3
- require 'doorkeeper/request/code'
4
- require 'doorkeeper/request/password'
5
- require 'doorkeeper/request/refresh_token'
6
- require 'doorkeeper/request/token'
7
-
8
1
  module Doorkeeper
9
2
  module Request
10
- module_function
3
+ class << self
4
+ def authorization_strategy(response_type)
5
+ get_strategy(response_type, authorization_response_types)
6
+ rescue NameError
7
+ raise Errors::InvalidAuthorizationStrategy
8
+ end
11
9
 
12
- def authorization_strategy(response_type)
13
- get_strategy response_type, authorization_response_types
14
- rescue NameError
15
- raise Errors::InvalidAuthorizationStrategy
16
- end
10
+ def token_strategy(grant_type)
11
+ get_strategy(grant_type, token_grant_types)
12
+ rescue NameError
13
+ raise Errors::InvalidTokenStrategy
14
+ end
17
15
 
18
- def token_strategy(grant_type)
19
- get_strategy grant_type, token_grant_types
20
- rescue NameError
21
- raise Errors::InvalidTokenStrategy
22
- end
16
+ def get_strategy(grant_or_request_type, available)
17
+ raise Errors::MissingRequestStrategy if grant_or_request_type.blank?
18
+ raise NameError unless available.include?(grant_or_request_type.to_s)
23
19
 
24
- def get_strategy(grant_or_request_type, available)
25
- fail Errors::MissingRequestStrategy unless grant_or_request_type.present?
26
- fail NameError unless available.include?(grant_or_request_type.to_s)
27
- strategy_class(grant_or_request_type)
28
- end
20
+ build_strategy_class(grant_or_request_type)
21
+ end
29
22
 
30
- def authorization_response_types
31
- Doorkeeper.configuration.authorization_response_types
32
- end
33
- private_class_method :authorization_response_types
23
+ private
34
24
 
35
- def token_grant_types
36
- Doorkeeper.configuration.token_grant_types
37
- end
38
- private_class_method :token_grant_types
25
+ def authorization_response_types
26
+ Doorkeeper.configuration.authorization_response_types
27
+ end
28
+
29
+ def token_grant_types
30
+ Doorkeeper.configuration.token_grant_types
31
+ end
39
32
 
40
- def strategy_class(grant_or_request_type)
41
- strategy_class_name = grant_or_request_type.to_s.tr(' ', '_').camelize
42
- "Doorkeeper::Request::#{strategy_class_name}".constantize
33
+ def build_strategy_class(grant_or_request_type)
34
+ strategy_class_name = grant_or_request_type.to_s.tr(' ', '_').camelize
35
+ "Doorkeeper::Request::#{strategy_class_name}".constantize
36
+ end
43
37
  end
44
- private_class_method :strategy_class
45
38
  end
46
39
  end
@@ -1,36 +1,16 @@
1
1
  module Doorkeeper
2
- CVE_2018_1000211_WARNING = <<-HEREDOC.freeze
3
-
4
-
5
- WARNING: This is a security release that addresses token revocation not working for public apps (CVE-2018-1000211)
6
-
7
- There is no breaking change in this release, however to take advantage of the security fix you must:
8
-
9
- 1. Run `rails generate doorkeeper:add_client_confidentiality` for the migration
10
- 2. Review your OAuth apps and determine which ones exclusively use public grant flows (eg implicit)
11
- 3. Update their `confidential` column to `false` for those public apps
12
-
13
- This is a backported security release.
14
-
15
- For more information:
16
-
17
- * https://github.com/doorkeeper-gem/doorkeeper/pull/1119
18
- * https://github.com/doorkeeper-gem/doorkeeper/issues/891
19
-
20
-
21
- HEREDOC
22
-
23
2
  def self.gem_version
24
3
  Gem::Version.new VERSION::STRING
25
4
  end
26
5
 
27
6
  module VERSION
28
7
  # Semantic versioning
29
- MAJOR = 4
30
- MINOR = 4
31
- TINY = 3
8
+ MAJOR = 5
9
+ MINOR = 0
10
+ TINY = 0
11
+ PRE = nil
32
12
 
33
13
  # Full version number
34
- STRING = [MAJOR, MINOR, TINY].compact.join('.')
14
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
35
15
  end
36
16
  end