doorkeeper 3.1.0 → 4.4.3

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 (195) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +25 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  5. data/.gitignore +6 -1
  6. data/.hound.yml +2 -13
  7. data/.rubocop.yml +17 -0
  8. data/.travis.yml +26 -10
  9. data/Appraisals +18 -0
  10. data/CODE_OF_CONDUCT.md +46 -0
  11. data/CONTRIBUTING.md +2 -0
  12. data/Gemfile +5 -5
  13. data/NEWS.md +141 -2
  14. data/README.md +149 -66
  15. data/RELEASING.md +5 -12
  16. data/Rakefile +1 -1
  17. data/SECURITY.md +15 -0
  18. data/app/controllers/doorkeeper/application_controller.rb +4 -6
  19. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  20. data/app/controllers/doorkeeper/applications_controller.rb +18 -8
  21. data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
  22. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  23. data/app/controllers/doorkeeper/tokens_controller.rb +62 -15
  24. data/app/helpers/doorkeeper/dashboard_helper.rb +14 -10
  25. data/app/validators/redirect_uri_validator.rb +12 -2
  26. data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
  27. data/app/views/doorkeeper/applications/_form.html.erb +13 -2
  28. data/app/views/doorkeeper/applications/index.html.erb +2 -0
  29. data/app/views/doorkeeper/applications/show.html.erb +4 -1
  30. data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
  31. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  32. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  33. data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
  34. data/config/locales/en.yml +12 -7
  35. data/doorkeeper.gemspec +16 -11
  36. data/gemfiles/rails_4_2.gemfile +13 -0
  37. data/gemfiles/rails_5_0.gemfile +12 -0
  38. data/gemfiles/rails_5_1.gemfile +12 -0
  39. data/gemfiles/rails_5_2.gemfile +12 -0
  40. data/gemfiles/rails_master.gemfile +14 -0
  41. data/lib/doorkeeper/config.rb +119 -46
  42. data/lib/doorkeeper/engine.rb +11 -7
  43. data/lib/doorkeeper/errors.rb +18 -0
  44. data/lib/doorkeeper/grape/helpers.rb +14 -8
  45. data/lib/doorkeeper/helpers/controller.rb +8 -19
  46. data/lib/doorkeeper/models/access_grant_mixin.rb +10 -21
  47. data/lib/doorkeeper/models/access_token_mixin.rb +147 -43
  48. data/lib/doorkeeper/models/application_mixin.rb +33 -35
  49. data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
  50. data/lib/doorkeeper/models/concerns/expirable.rb +15 -5
  51. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  52. data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
  53. data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
  54. data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
  55. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
  56. data/lib/doorkeeper/oauth/authorization_code_request.rb +7 -5
  57. data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +9 -2
  58. data/lib/doorkeeper/oauth/base_response.rb +29 -0
  59. data/lib/doorkeeper/oauth/client/credentials.rb +21 -8
  60. data/lib/doorkeeper/oauth/client.rb +2 -3
  61. data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
  62. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  63. data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
  64. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
  65. data/lib/doorkeeper/oauth/code_response.rb +16 -16
  66. data/lib/doorkeeper/oauth/error.rb +2 -2
  67. data/lib/doorkeeper/oauth/error_response.rb +10 -10
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +17 -1
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -4
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -13
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +5 -3
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +23 -14
  75. data/lib/doorkeeper/oauth/scopes.rb +18 -8
  76. data/lib/doorkeeper/oauth/token.rb +20 -21
  77. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  78. data/lib/doorkeeper/oauth/token_request.rb +1 -2
  79. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  80. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  81. data/lib/doorkeeper/orm/active_record/access_token.rb +34 -8
  82. data/lib/doorkeeper/orm/active_record/application.rb +48 -11
  83. data/lib/doorkeeper/orm/active_record.rb +17 -22
  84. data/lib/doorkeeper/rails/helpers.rb +6 -9
  85. data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
  86. data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
  87. data/lib/doorkeeper/rails/routes.rb +17 -11
  88. data/lib/doorkeeper/request/authorization_code.rb +7 -1
  89. data/lib/doorkeeper/request/password.rb +2 -2
  90. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  91. data/lib/doorkeeper/request.rb +7 -1
  92. data/lib/doorkeeper/server.rb +0 -8
  93. data/lib/doorkeeper/validations.rb +3 -2
  94. data/lib/doorkeeper/version.rb +34 -1
  95. data/lib/doorkeeper.rb +10 -2
  96. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +31 -0
  97. data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
  98. data/lib/generators/doorkeeper/migration_generator.rb +13 -1
  99. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +35 -0
  100. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +11 -0
  101. data/{spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb → lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb} +1 -1
  102. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +11 -0
  103. data/lib/generators/doorkeeper/templates/initializer.rb +38 -6
  104. data/lib/generators/doorkeeper/templates/migration.rb.erb +69 -0
  105. data/spec/controllers/application_metal_controller.rb +10 -0
  106. data/spec/controllers/applications_controller_spec.rb +15 -4
  107. data/spec/controllers/authorizations_controller_spec.rb +74 -27
  108. data/spec/controllers/protected_resources_controller_spec.rb +70 -32
  109. data/spec/controllers/token_info_controller_spec.rb +17 -13
  110. data/spec/controllers/tokens_controller_spec.rb +198 -12
  111. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
  112. data/spec/dummy/app/controllers/home_controller.rb +1 -1
  113. data/spec/dummy/app/controllers/metal_controller.rb +1 -1
  114. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
  115. data/spec/dummy/app/models/user.rb +0 -4
  116. data/spec/dummy/config/application.rb +2 -36
  117. data/spec/dummy/config/environment.rb +1 -1
  118. data/spec/dummy/config/environments/test.rb +4 -15
  119. data/spec/dummy/config/initializers/doorkeeper.rb +19 -3
  120. data/spec/dummy/config/initializers/new_framework_defaults.rb +6 -0
  121. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  122. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  123. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  124. data/{lib/generators/doorkeeper/templates/migration.rb → spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb} +16 -4
  125. data/{lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb → spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb} +4 -2
  126. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +13 -0
  127. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb +13 -0
  128. data/spec/dummy/db/schema.rb +24 -22
  129. data/spec/factories.rb +4 -2
  130. data/spec/generators/application_owner_generator_spec.rb +24 -5
  131. data/spec/generators/migration_generator_spec.rb +24 -3
  132. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  133. data/spec/grape/grape_integration_spec.rb +135 -0
  134. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  135. data/spec/lib/config_spec.rb +159 -14
  136. data/spec/lib/doorkeeper_spec.rb +135 -13
  137. data/spec/lib/models/expirable_spec.rb +0 -1
  138. data/spec/lib/models/revocable_spec.rb +27 -4
  139. data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
  140. data/spec/lib/oauth/authorization_code_request_spec.rb +55 -12
  141. data/spec/lib/oauth/base_request_spec.rb +155 -0
  142. data/spec/lib/oauth/base_response_spec.rb +45 -0
  143. data/spec/lib/oauth/client/credentials_spec.rb +45 -2
  144. data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
  145. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  146. data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
  147. data/spec/lib/oauth/code_request_spec.rb +1 -3
  148. data/spec/lib/oauth/code_response_spec.rb +34 -0
  149. data/spec/lib/oauth/error_response_spec.rb +9 -9
  150. data/spec/lib/oauth/error_spec.rb +1 -1
  151. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -1
  152. data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
  153. data/spec/lib/oauth/password_access_token_request_spec.rb +14 -8
  154. data/spec/lib/oauth/pre_authorization_spec.rb +12 -7
  155. data/spec/lib/oauth/refresh_token_request_spec.rb +52 -9
  156. data/spec/lib/oauth/scopes_spec.rb +28 -2
  157. data/spec/lib/oauth/token_request_spec.rb +6 -8
  158. data/spec/lib/oauth/token_spec.rb +12 -5
  159. data/spec/lib/server_spec.rb +10 -3
  160. data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
  161. data/spec/models/doorkeeper/access_token_spec.rb +116 -48
  162. data/spec/models/doorkeeper/application_spec.rb +145 -29
  163. data/spec/requests/applications/applications_request_spec.rb +5 -5
  164. data/spec/requests/endpoints/authorization_spec.rb +5 -6
  165. data/spec/requests/endpoints/token_spec.rb +8 -1
  166. data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
  167. data/spec/requests/flows/authorization_code_spec.rb +6 -13
  168. data/spec/requests/flows/client_credentials_spec.rb +29 -1
  169. data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
  170. data/spec/requests/flows/password_spec.rb +118 -15
  171. data/spec/requests/flows/refresh_token_spec.rb +89 -19
  172. data/spec/requests/flows/revoke_token_spec.rb +105 -91
  173. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  174. data/spec/requests/protected_resources/private_api_spec.rb +1 -1
  175. data/spec/routing/custom_controller_routes_spec.rb +4 -0
  176. data/spec/routing/default_routes_spec.rb +5 -1
  177. data/spec/spec_helper.rb +2 -0
  178. data/spec/spec_helper_integration.rb +22 -4
  179. data/spec/support/dependencies/factory_girl.rb +2 -2
  180. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  181. data/spec/support/helpers/model_helper.rb +34 -7
  182. data/spec/support/helpers/request_spec_helper.rb +17 -5
  183. data/spec/support/helpers/url_helper.rb +9 -8
  184. data/spec/support/http_method_shim.rb +38 -0
  185. data/spec/support/shared/controllers_shared_context.rb +15 -10
  186. data/spec/support/shared/models_shared_examples.rb +5 -5
  187. data/spec/validators/redirect_uri_validator_spec.rb +51 -6
  188. data/spec/version/version_spec.rb +15 -0
  189. metadata +128 -46
  190. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  191. data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
  192. data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
  193. data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
  194. data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
  195. data/spec/lib/oauth/client/methods_spec.rb +0 -54
@@ -3,9 +3,8 @@ require 'doorkeeper/rails/routes/mapper'
3
3
 
4
4
  module Doorkeeper
5
5
  module Rails
6
- class Routes
6
+ class Routes # :nodoc:
7
7
  module Helper
8
- # TODO: options hash is not being used
9
8
  def use_doorkeeper(options = {}, &block)
10
9
  Doorkeeper::Rails::Routes.new(self, &block).generate_routes!(options)
11
10
  end
@@ -15,18 +14,19 @@ module Doorkeeper
15
14
  ActionDispatch::Routing::Mapper.send :include, Doorkeeper::Rails::Routes::Helper
16
15
  end
17
16
 
18
- attr_accessor :routes
17
+ attr_reader :routes
19
18
 
20
19
  def initialize(routes, &block)
21
- @routes, @block = routes, block
20
+ @routes = routes
21
+ @mapping = Mapper.new.map(&block)
22
22
  end
23
23
 
24
24
  def generate_routes!(options)
25
- @mapping = Mapper.new.map(&@block)
26
25
  routes.scope options[:scope] || 'oauth', as: 'oauth' do
27
26
  map_route(:authorizations, :authorization_routes)
28
27
  map_route(:tokens, :token_routes)
29
28
  map_route(:tokens, :revoke_routes)
29
+ map_route(:tokens, :introspect_routes)
30
30
  map_route(:applications, :application_routes)
31
31
  map_route(:authorized_applications, :authorized_applications_routes)
32
32
  map_route(:token_info, :token_info_routes)
@@ -36,20 +36,18 @@ module Doorkeeper
36
36
  private
37
37
 
38
38
  def map_route(name, method)
39
- unless @mapping.skipped?(name)
40
- send method, @mapping[name]
41
- end
39
+ send(method, @mapping[name]) unless @mapping.skipped?(name)
42
40
  end
43
41
 
44
42
  def authorization_routes(mapping)
45
43
  routes.resource(
46
44
  :authorization,
47
45
  path: 'authorize',
48
- only: [:create, :destroy],
46
+ only: %i[create destroy],
49
47
  as: mapping[:as],
50
48
  controller: mapping[:controllers]
51
49
  ) do
52
- routes.get '/:code', action: :show, on: :member
50
+ routes.get native_authorization_code_route, action: :show, on: :member
53
51
  routes.get '/', action: :new, on: :member
54
52
  end
55
53
  end
@@ -67,6 +65,10 @@ module Doorkeeper
67
65
  routes.post 'revoke', controller: mapping[:controllers], action: :revoke
68
66
  end
69
67
 
68
+ def introspect_routes(mapping)
69
+ routes.post 'introspect', controller: mapping[:controllers], action: :introspect
70
+ end
71
+
70
72
  def token_info_routes(mapping)
71
73
  routes.resource(
72
74
  :token_info,
@@ -81,7 +83,11 @@ module Doorkeeper
81
83
  end
82
84
 
83
85
  def authorized_applications_routes(mapping)
84
- routes.resources :authorized_applications, only: [:index, :destroy], controller: mapping[:controllers]
86
+ routes.resources :authorized_applications, only: %i[index destroy], controller: mapping[:controllers]
87
+ end
88
+
89
+ def native_authorization_code_route
90
+ Doorkeeper.configuration.native_authorization_code_route
85
91
  end
86
92
  end
87
93
  end
@@ -3,7 +3,7 @@ require 'doorkeeper/request/strategy'
3
3
  module Doorkeeper
4
4
  module Request
5
5
  class AuthorizationCode < Strategy
6
- delegate :grant, :client, :parameters, to: :server
6
+ delegate :client, :parameters, to: :server
7
7
 
8
8
  def request
9
9
  @request ||= OAuth::AuthorizationCodeRequest.new(
@@ -13,6 +13,12 @@ module Doorkeeper
13
13
  parameters
14
14
  )
15
15
  end
16
+
17
+ private
18
+
19
+ def grant
20
+ AccessGrant.by_token(parameters[:code])
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -3,12 +3,12 @@ require 'doorkeeper/request/strategy'
3
3
  module Doorkeeper
4
4
  module Request
5
5
  class Password < Strategy
6
- delegate :credentials, :resource_owner, :parameters, to: :server
6
+ delegate :credentials, :resource_owner, :parameters, :client, to: :server
7
7
 
8
8
  def request
9
9
  @request ||= OAuth::PasswordAccessTokenRequest.new(
10
10
  Doorkeeper.configuration,
11
- credentials,
11
+ client,
12
12
  resource_owner,
13
13
  parameters
14
14
  )
@@ -6,7 +6,7 @@ module Doorkeeper
6
6
  delegate :credentials, :parameters, to: :server
7
7
 
8
8
  def refresh_token
9
- server.current_refresh_token
9
+ AccessToken.by_refresh_token(parameters[:refresh_token])
10
10
  end
11
11
 
12
12
  def request
@@ -24,7 +24,7 @@ module Doorkeeper
24
24
  def get_strategy(grant_or_request_type, available)
25
25
  fail Errors::MissingRequestStrategy unless grant_or_request_type.present?
26
26
  fail NameError unless available.include?(grant_or_request_type.to_s)
27
- "Doorkeeper::Request::#{grant_or_request_type.to_s.camelize}".constantize
27
+ strategy_class(grant_or_request_type)
28
28
  end
29
29
 
30
30
  def authorization_response_types
@@ -36,5 +36,11 @@ module Doorkeeper
36
36
  Doorkeeper.configuration.token_grant_types
37
37
  end
38
38
  private_class_method :token_grant_types
39
+
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
43
+ end
44
+ private_class_method :strategy_class
39
45
  end
40
46
  end
@@ -33,14 +33,6 @@ module Doorkeeper
33
33
  context.send :current_resource_owner
34
34
  end
35
35
 
36
- def current_refresh_token
37
- AccessToken.by_refresh_token(parameters[:refresh_token])
38
- end
39
-
40
- def grant
41
- AccessGrant.by_token(parameters[:code])
42
- end
43
-
44
36
  # TODO: Use configuration and evaluate proper context on block
45
37
  def resource_owner
46
38
  context.send :resource_owner_from_credentials
@@ -6,9 +6,10 @@ module Doorkeeper
6
6
 
7
7
  def validate
8
8
  @error = nil
9
+
9
10
  self.class.validations.each do |validation|
11
+ @error = validation[:options][:error] unless send("validate_#{validation[:attribute]}")
10
12
  break if @error
11
- @error = validation.last unless send("validate_#{validation.first}")
12
13
  end
13
14
  end
14
15
 
@@ -19,7 +20,7 @@ module Doorkeeper
19
20
 
20
21
  module ClassMethods
21
22
  def validate(attribute, options = {})
22
- validations << [attribute, options[:error]]
23
+ validations << { attribute: attribute, options: options }
23
24
  end
24
25
 
25
26
  def validations
@@ -1,3 +1,36 @@
1
1
  module Doorkeeper
2
- VERSION = "3.1.0"
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
+ def self.gem_version
24
+ Gem::Version.new VERSION::STRING
25
+ end
26
+
27
+ module VERSION
28
+ # Semantic versioning
29
+ MAJOR = 4
30
+ MINOR = 4
31
+ TINY = 3
32
+
33
+ # Full version number
34
+ STRING = [MAJOR, MINOR, TINY].compact.join('.')
35
+ end
3
36
  end
data/lib/doorkeeper.rb CHANGED
@@ -16,11 +16,12 @@ require 'doorkeeper/oauth/helpers/unique_token'
16
16
 
17
17
  require 'doorkeeper/oauth/scopes'
18
18
  require 'doorkeeper/oauth/error'
19
+ require 'doorkeeper/oauth/base_response'
19
20
  require 'doorkeeper/oauth/code_response'
20
21
  require 'doorkeeper/oauth/token_response'
21
22
  require 'doorkeeper/oauth/error_response'
22
23
  require 'doorkeeper/oauth/pre_authorization'
23
- require 'doorkeeper/oauth/request_concern'
24
+ require 'doorkeeper/oauth/base_request'
24
25
  require 'doorkeeper/oauth/authorization_code_request'
25
26
  require 'doorkeeper/oauth/refresh_token_request'
26
27
  require 'doorkeeper/oauth/password_access_token_request'
@@ -29,9 +30,11 @@ require 'doorkeeper/oauth/code_request'
29
30
  require 'doorkeeper/oauth/token_request'
30
31
  require 'doorkeeper/oauth/client'
31
32
  require 'doorkeeper/oauth/token'
33
+ require 'doorkeeper/oauth/token_introspection'
32
34
  require 'doorkeeper/oauth/invalid_token_response'
33
35
  require 'doorkeeper/oauth/forbidden_token_response'
34
36
 
37
+ require 'doorkeeper/models/concerns/orderable'
35
38
  require 'doorkeeper/models/concerns/scopes'
36
39
  require 'doorkeeper/models/concerns/expirable'
37
40
  require 'doorkeeper/models/concerns/revocable'
@@ -48,16 +51,21 @@ require 'doorkeeper/rails/helpers'
48
51
 
49
52
  require 'doorkeeper/orm/active_record'
50
53
 
54
+ require 'active_support/deprecation'
55
+
51
56
  module Doorkeeper
52
57
  def self.configured?
58
+ ActiveSupport::Deprecation.warn "Method `Doorkeeper#configured?` has been deprecated without replacement."
53
59
  @config.present?
54
60
  end
55
61
 
56
62
  def self.database_installed?
57
- [AccessToken, AccessGrant, Application].all? { |model| model.table_exists? }
63
+ ActiveSupport::Deprecation.warn "Method `Doorkeeper#database_installed?` has been deprecated without replacement."
64
+ [AccessToken, AccessGrant, Application].all?(&:table_exists?)
58
65
  end
59
66
 
60
67
  def self.installed?
68
+ ActiveSupport::Deprecation.warn "Method `Doorkeeper#installed?` has been deprecated without replacement."
61
69
  configured? && database_installed?
62
70
  end
63
71
 
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/active_record'
4
+
5
+ module Doorkeeper
6
+ class AddClientConfidentialityGenerator < ::Rails::Generators::Base
7
+ include ::Rails::Generators::Migration
8
+ source_root File.expand_path('templates', __dir__)
9
+ desc 'Adds a migration to fix CVE-2018-1000211.'
10
+
11
+ def install
12
+ migration_template(
13
+ 'add_confidential_to_application_migration.rb.erb',
14
+ 'db/migrate/add_confidential_to_doorkeeper_application.rb',
15
+ migration_version: migration_version
16
+ )
17
+ end
18
+
19
+ def self.next_migration_number(dirname)
20
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
21
+ end
22
+
23
+ private
24
+
25
+ def migration_version
26
+ if ::ActiveRecord::VERSION::MAJOR >= 5
27
+ "[#{::ActiveRecord::VERSION::MAJOR}.#{::ActiveRecord::VERSION::MINOR}]"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -7,12 +7,21 @@ class Doorkeeper::ApplicationOwnerGenerator < Rails::Generators::Base
7
7
 
8
8
  def application_owner
9
9
  migration_template(
10
- 'add_owner_to_application_migration.rb',
11
- 'db/migrate/add_owner_to_application.rb'
10
+ 'add_owner_to_application_migration.rb.erb',
11
+ 'db/migrate/add_owner_to_application.rb',
12
+ migration_version: migration_version
12
13
  )
13
14
  end
14
15
 
15
16
  def self.next_migration_number(dirname)
16
17
  ActiveRecord::Generators::Base.next_migration_number(dirname)
17
18
  end
19
+
20
+ private
21
+
22
+ def migration_version
23
+ if ActiveRecord::VERSION::MAJOR >= 5
24
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
25
+ end
26
+ end
18
27
  end
@@ -6,10 +6,22 @@ class Doorkeeper::MigrationGenerator < ::Rails::Generators::Base
6
6
  desc 'Installs Doorkeeper migration file.'
7
7
 
8
8
  def install
9
- migration_template 'migration.rb', 'db/migrate/create_doorkeeper_tables.rb'
9
+ migration_template(
10
+ 'migration.rb.erb',
11
+ 'db/migrate/create_doorkeeper_tables.rb',
12
+ migration_version: migration_version
13
+ )
10
14
  end
11
15
 
12
16
  def self.next_migration_number(dirname)
13
17
  ActiveRecord::Generators::Base.next_migration_number(dirname)
14
18
  end
19
+
20
+ private
21
+
22
+ def migration_version
23
+ if ActiveRecord::VERSION::MAJOR >= 5
24
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
25
+ end
26
+ end
15
27
  end
@@ -0,0 +1,35 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ class Doorkeeper::PreviousRefreshTokenGenerator < Rails::Generators::Base
4
+ include Rails::Generators::Migration
5
+ source_root File.expand_path('../templates', __FILE__)
6
+ desc 'Support revoke refresh token on access token use'
7
+
8
+ def self.next_migration_number(path)
9
+ ActiveRecord::Generators::Base.next_migration_number(path)
10
+ end
11
+
12
+ def previous_refresh_token
13
+ if no_previous_refresh_token_column?
14
+ migration_template(
15
+ 'add_previous_refresh_token_to_access_tokens.rb.erb',
16
+ 'db/migrate/add_previous_refresh_token_to_access_tokens.rb'
17
+ )
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def migration_version
24
+ if ActiveRecord::VERSION::MAJOR >= 5
25
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
26
+ end
27
+ end
28
+
29
+ def no_previous_refresh_token_column?
30
+ !ActiveRecord::Base.connection.column_exists?(
31
+ :oauth_access_tokens,
32
+ :previous_refresh_token
33
+ )
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ class AddConfidentialToDoorkeeperApplication < ActiveRecord::Migration<%= migration_version %>
2
+ def change
3
+ add_column(
4
+ :oauth_applications,
5
+ :confidential,
6
+ :boolean,
7
+ null: false,
8
+ default: true # maintaining backwards compatibility: require secrets
9
+ )
10
+ end
11
+ end
@@ -1,4 +1,4 @@
1
- class AddOwnerToApplication < ActiveRecord::Migration
1
+ class AddOwnerToApplication < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
3
  add_column :oauth_applications, :owner_id, :integer, null: true
4
4
  add_column :oauth_applications, :owner_type, :string, null: true
@@ -0,0 +1,11 @@
1
+ class AddPreviousRefreshTokenToAccessTokens < ActiveRecord::Migration<%= migration_version %>
2
+ def change
3
+ add_column(
4
+ :oauth_access_tokens,
5
+ :previous_refresh_token,
6
+ :string,
7
+ default: "",
8
+ null: false
9
+ )
10
+ end
11
+ end
@@ -31,7 +31,12 @@ Doorkeeper.configure do
31
31
 
32
32
  # Use a custom class for generating the access token.
33
33
  # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
34
- # access_token_generator "::Doorkeeper::JWT"
34
+ # access_token_generator '::Doorkeeper::JWT'
35
+
36
+ # The controller Doorkeeper::ApplicationController inherits from.
37
+ # Defaults to ActionController::Base.
38
+ # https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
39
+ # base_controller 'ApplicationController'
35
40
 
36
41
  # Reuse access token for the same resource owner within an application (disabled by default)
37
42
  # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
@@ -41,10 +46,10 @@ Doorkeeper.configure do
41
46
  # use_refresh_token
42
47
 
43
48
  # Provide support for an owner to be assigned to each registered application (disabled by default)
44
- # Optional parameter :confirmation => true (default false) if you want to enforce ownership of
49
+ # Optional parameter confirmation: true (default false) if you want to enforce ownership of
45
50
  # a registered application
46
51
  # Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
47
- # enable_application_owner :confirmation => false
52
+ # enable_application_owner confirmation: false
48
53
 
49
54
  # Define access token scopes for your provider
50
55
  # For more information go to
@@ -55,13 +60,15 @@ Doorkeeper.configure do
55
60
  # Change the way client credentials are retrieved from the request object.
56
61
  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
57
62
  # falls back to the `:client_id` and `:client_secret` params from the `params` object.
58
- # Check out the wiki for more information on customization
63
+ # Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated
64
+ # for more information on customization
59
65
  # client_credentials :from_basic, :from_params
60
66
 
61
67
  # Change the way access token is authenticated from the request object.
62
68
  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
63
69
  # falls back to the `:access_token` or `:bearer_token` params from the `params` object.
64
- # Check out the wiki for more information on customization
70
+ # Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated
71
+ # for more information on customization
65
72
  # access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
66
73
 
67
74
  # Change the native redirect uri for client apps
@@ -75,7 +82,21 @@ Doorkeeper.configure do
75
82
  # by default in non-development environments). OAuth2 delegates security in
76
83
  # communication to the HTTPS protocol so it is wise to keep this enabled.
77
84
  #
85
+ # Callable objects such as proc, lambda, block or any object that responds to
86
+ # #call can be used in order to allow conditional checks (to allow non-SSL
87
+ # redirects to localhost for example).
88
+ #
78
89
  # force_ssl_in_redirect_uri !Rails.env.development?
90
+ #
91
+ # force_ssl_in_redirect_uri { |uri| uri.host != 'localhost' }
92
+
93
+ # Specify what redirect URI's you want to block during creation. Any redirect
94
+ # URI is whitelisted by default.
95
+ #
96
+ # You can use this option in order to forbid URI's with 'javascript' scheme
97
+ # for example.
98
+ #
99
+ # forbid_redirect_uri { |uri| uri.scheme.to_s.downcase == 'javascript' }
79
100
 
80
101
  # Specify what grant flows are enabled in array of Strings. The valid
81
102
  # strings and the flows they enable are:
@@ -93,7 +114,18 @@ Doorkeeper.configure do
93
114
  # http://tools.ietf.org/html/rfc6819#section-4.4.2
94
115
  # http://tools.ietf.org/html/rfc6819#section-4.4.3
95
116
  #
96
- # grant_flows %w(authorization_code client_credentials)
117
+ # grant_flows %w[authorization_code client_credentials]
118
+
119
+ # Hook into the strategies' request & response life-cycle in case your
120
+ # application needs advanced customization or logging:
121
+ #
122
+ # before_successful_strategy_response do |request|
123
+ # puts "BEFORE HOOK FIRED! #{request}"
124
+ # end
125
+ #
126
+ # after_successful_strategy_response do |request, response|
127
+ # puts "AFTER HOOK FIRED! #{request}, #{response}"
128
+ # end
97
129
 
98
130
  # Under some circumstances you might want to have applications auto-approved,
99
131
  # so that the user skips the authorization step.
@@ -0,0 +1,69 @@
1
+ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
2
+ def change
3
+ create_table :oauth_applications do |t|
4
+ t.string :name, null: false
5
+ t.string :uid, null: false
6
+ t.string :secret, null: false
7
+ t.text :redirect_uri, null: false
8
+ t.string :scopes, null: false, default: ''
9
+ t.boolean :confidential, null: false, default: true
10
+ t.timestamps null: false
11
+ end
12
+
13
+ add_index :oauth_applications, :uid, unique: true
14
+
15
+ create_table :oauth_access_grants do |t|
16
+ t.integer :resource_owner_id, null: false
17
+ t.references :application, null: false
18
+ t.string :token, null: false
19
+ t.integer :expires_in, null: false
20
+ t.text :redirect_uri, null: false
21
+ t.datetime :created_at, null: false
22
+ t.datetime :revoked_at
23
+ t.string :scopes
24
+ end
25
+
26
+ add_index :oauth_access_grants, :token, unique: true
27
+ add_foreign_key(
28
+ :oauth_access_grants,
29
+ :oauth_applications,
30
+ column: :application_id
31
+ )
32
+
33
+ create_table :oauth_access_tokens do |t|
34
+ t.integer :resource_owner_id
35
+ t.references :application
36
+
37
+ # If you use a custom token generator you may need to change this column
38
+ # from string to text, so that it accepts tokens larger than 255
39
+ # characters. More info on custom token generators in:
40
+ # https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
41
+ #
42
+ # t.text :token, null: false
43
+ t.string :token, null: false
44
+
45
+ t.string :refresh_token
46
+ t.integer :expires_in
47
+ t.datetime :revoked_at
48
+ t.datetime :created_at, null: false
49
+ t.string :scopes
50
+
51
+ # If there is a previous_refresh_token column,
52
+ # refresh tokens will be revoked after a related access token is used.
53
+ # If there is no previous_refresh_token column,
54
+ # previous tokens are revoked as soon as a new access token is created.
55
+ # Comment out this line if you'd rather have refresh tokens
56
+ # instantly revoked.
57
+ t.string :previous_refresh_token, null: false, default: ""
58
+ end
59
+
60
+ add_index :oauth_access_tokens, :token, unique: true
61
+ add_index :oauth_access_tokens, :resource_owner_id
62
+ add_index :oauth_access_tokens, :refresh_token, unique: true
63
+ add_foreign_key(
64
+ :oauth_access_tokens,
65
+ :oauth_applications,
66
+ column: :application_id
67
+ )
68
+ end
69
+ end
@@ -0,0 +1,10 @@
1
+ require "spec_helper_integration"
2
+
3
+ describe Doorkeeper::ApplicationMetalController do
4
+ it "lazy run hooks" do
5
+ i = 0
6
+ ActiveSupport.on_load(:doorkeeper_metal_controller) { i += 1 }
7
+
8
+ expect(i).to eq 1
9
+ end
10
+ end
@@ -19,13 +19,24 @@ module Doorkeeper
19
19
  post :create, doorkeeper_application: {
20
20
  name: 'Example',
21
21
  redirect_uri: 'https://example.com' }
22
- end.to_not change { Doorkeeper::Application.count }
22
+ end.not_to change { Doorkeeper::Application.count }
23
23
  end
24
24
  end
25
25
 
26
26
  context 'when admin is authenticated' do
27
+ render_views
28
+
27
29
  before do
28
- allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(arg) { true })
30
+ allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) { true })
31
+ end
32
+
33
+ it 'sorts applications by created_at' do
34
+ first_application = FactoryBot.create(:application)
35
+ second_application = FactoryBot.create(:application)
36
+ expect(Doorkeeper::Application).to receive(:ordered_by).and_call_original
37
+ get :index
38
+ expect(response.body).to have_selector("tbody tr:first-child#application_#{first_application.id}")
39
+ expect(response.body).to have_selector("tbody tr:last-child#application_#{second_application.id}")
29
40
  end
30
41
 
31
42
  it 'creates application' do
@@ -38,7 +49,7 @@ module Doorkeeper
38
49
  end
39
50
 
40
51
  it 'does not allow mass assignment of uid or secret' do
41
- application = FactoryGirl.create(:application)
52
+ application = FactoryBot.create(:application)
42
53
  put :update, id: application.id, doorkeeper_application: {
43
54
  uid: '1A2B3C4D',
44
55
  secret: '1A2B3C4D' }
@@ -47,7 +58,7 @@ module Doorkeeper
47
58
  end
48
59
 
49
60
  it 'updates application' do
50
- application = FactoryGirl.create(:application)
61
+ application = FactoryBot.create(:application)
51
62
  put :update, id: application.id, doorkeeper_application: {
52
63
  name: 'Example',
53
64
  redirect_uri: 'https://example.com' }