doorkeeper 4.2.5 → 4.3.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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +19 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  4. data/.gitignore +1 -1
  5. data/.hound.yml +2 -13
  6. data/.rubocop.yml +13 -0
  7. data/.travis.yml +13 -4
  8. data/Appraisals +6 -2
  9. data/CODE_OF_CONDUCT.md +46 -0
  10. data/Gemfile +1 -1
  11. data/NEWS.md +28 -0
  12. data/README.md +40 -10
  13. data/RELEASING.md +5 -12
  14. data/SECURITY.md +13 -0
  15. data/app/controllers/doorkeeper/application_controller.rb +1 -5
  16. data/app/controllers/doorkeeper/applications_controller.rb +14 -1
  17. data/app/controllers/doorkeeper/tokens_controller.rb +13 -1
  18. data/app/helpers/doorkeeper/dashboard_helper.rb +4 -2
  19. data/app/validators/redirect_uri_validator.rb +12 -2
  20. data/app/views/doorkeeper/applications/_form.html.erb +2 -2
  21. data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
  22. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  23. data/config/locales/en.yml +3 -5
  24. data/doorkeeper.gemspec +4 -4
  25. data/gemfiles/rails_4_2.gemfile +6 -4
  26. data/gemfiles/rails_5_0.gemfile +4 -4
  27. data/gemfiles/rails_5_1.gemfile +6 -7
  28. data/gemfiles/rails_5_2.gemfile +12 -0
  29. data/gemfiles/rails_master.gemfile +14 -0
  30. data/lib/doorkeeper/config.rb +55 -55
  31. data/lib/doorkeeper/engine.rb +3 -3
  32. data/lib/doorkeeper/errors.rb +18 -0
  33. data/lib/doorkeeper/grape/helpers.rb +13 -8
  34. data/lib/doorkeeper/helpers/controller.rb +9 -20
  35. data/lib/doorkeeper/models/access_token_mixin.rb +14 -7
  36. data/lib/doorkeeper/models/application_mixin.rb +11 -6
  37. data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
  38. data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
  39. data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -1
  40. data/lib/doorkeeper/oauth/base_request.rb +5 -5
  41. data/lib/doorkeeper/oauth/client/credentials.rb +2 -2
  42. data/lib/doorkeeper/oauth/client.rb +2 -2
  43. data/lib/doorkeeper/oauth/error.rb +2 -2
  44. data/lib/doorkeeper/oauth/error_response.rb +1 -2
  45. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  46. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -3
  47. data/lib/doorkeeper/oauth/password_access_token_request.rb +1 -0
  48. data/lib/doorkeeper/oauth/refresh_token_request.rb +1 -0
  49. data/lib/doorkeeper/oauth/scopes.rb +18 -8
  50. data/lib/doorkeeper/oauth/token.rb +1 -1
  51. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  52. data/lib/doorkeeper/orm/active_record/access_grant.rb +1 -1
  53. data/lib/doorkeeper/orm/active_record/access_token.rb +1 -23
  54. data/lib/doorkeeper/orm/active_record/application.rb +1 -1
  55. data/lib/doorkeeper/orm/active_record/base_record.rb +11 -0
  56. data/lib/doorkeeper/orm/active_record.rb +20 -8
  57. data/lib/doorkeeper/rails/helpers.rb +5 -6
  58. data/lib/doorkeeper/rails/routes.rb +9 -7
  59. data/lib/doorkeeper/request.rb +7 -1
  60. data/lib/doorkeeper/validations.rb +3 -2
  61. data/lib/doorkeeper/version.rb +13 -1
  62. data/lib/doorkeeper.rb +1 -0
  63. data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
  64. data/lib/generators/doorkeeper/migration_generator.rb +13 -1
  65. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -1
  66. data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
  67. data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
  68. data/lib/generators/doorkeeper/templates/initializer.rb +19 -3
  69. data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +1 -1
  70. data/spec/controllers/applications_controller_spec.rb +15 -4
  71. data/spec/controllers/authorizations_controller_spec.rb +31 -16
  72. data/spec/controllers/protected_resources_controller_spec.rb +28 -19
  73. data/spec/controllers/token_info_controller_spec.rb +17 -13
  74. data/spec/controllers/tokens_controller_spec.rb +138 -4
  75. data/spec/dummy/config/initializers/doorkeeper.rb +1 -1
  76. data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +1 -1
  77. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  78. data/spec/factories.rb +1 -1
  79. data/spec/generators/application_owner_generator_spec.rb +24 -5
  80. data/spec/generators/migration_generator_spec.rb +24 -3
  81. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  82. data/spec/grape/grape_integration_spec.rb +135 -0
  83. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  84. data/spec/lib/config_spec.rb +115 -12
  85. data/spec/lib/models/expirable_spec.rb +0 -1
  86. data/spec/lib/models/revocable_spec.rb +2 -2
  87. data/spec/lib/oauth/authorization_code_request_spec.rb +39 -11
  88. data/spec/lib/oauth/base_request_spec.rb +2 -7
  89. data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
  90. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  91. data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
  92. data/spec/lib/oauth/code_request_spec.rb +1 -3
  93. data/spec/lib/oauth/helpers/uri_checker_spec.rb +5 -0
  94. data/spec/lib/oauth/invalid_token_response_spec.rb +1 -1
  95. data/spec/lib/oauth/password_access_token_request_spec.rb +9 -3
  96. data/spec/lib/oauth/refresh_token_request_spec.rb +19 -7
  97. data/spec/lib/oauth/scopes_spec.rb +28 -1
  98. data/spec/lib/oauth/token_request_spec.rb +6 -8
  99. data/spec/lib/server_spec.rb +10 -0
  100. data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
  101. data/spec/models/doorkeeper/access_token_spec.rb +72 -48
  102. data/spec/models/doorkeeper/application_spec.rb +51 -18
  103. data/spec/requests/applications/applications_request_spec.rb +5 -5
  104. data/spec/requests/endpoints/token_spec.rb +8 -1
  105. data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
  106. data/spec/requests/flows/authorization_code_spec.rb +1 -0
  107. data/spec/requests/flows/client_credentials_spec.rb +1 -1
  108. data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
  109. data/spec/requests/flows/refresh_token_spec.rb +4 -4
  110. data/spec/requests/flows/revoke_token_spec.rb +15 -15
  111. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  112. data/spec/requests/protected_resources/private_api_spec.rb +1 -1
  113. data/spec/routing/custom_controller_routes_spec.rb +4 -0
  114. data/spec/routing/default_routes_spec.rb +5 -1
  115. data/spec/spec_helper_integration.rb +15 -5
  116. data/spec/support/dependencies/factory_girl.rb +2 -2
  117. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  118. data/spec/support/helpers/model_helper.rb +9 -4
  119. data/spec/support/helpers/request_spec_helper.rb +7 -3
  120. data/spec/support/helpers/url_helper.rb +8 -8
  121. data/spec/support/shared/controllers_shared_context.rb +2 -6
  122. data/spec/support/shared/models_shared_examples.rb +4 -4
  123. data/spec/validators/redirect_uri_validator_spec.rb +51 -6
  124. data/spec/version/version_spec.rb +15 -0
  125. metadata +42 -27
@@ -2,12 +2,11 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", :github => "rails/rails"
5
+ gem "rails", "~> 5.1.0"
6
6
  gem "appraisal"
7
- gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
8
- gem "sqlite3", :platform => [:ruby, :mswin, :mingw, :x64_mingw]
9
- gem "tzinfo-data", :platforms => [:mingw, :mswin, :x64_mingw]
10
- gem "arel", :github => "rails/arel"
11
- gem "rspec-rails", "~> 3.5"
7
+ gem "activerecord-jdbcsqlite3-adapter", platforms: :jruby
8
+ gem "sqlite3", platforms: [:ruby, :mswin, :mingw, :x64_mingw]
9
+ gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
10
+ gem "rspec-rails", "~> 3.7"
12
11
 
13
- gemspec :path => "../"
12
+ gemspec path: "../"
@@ -0,0 +1,12 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "5.2.0.rc1"
6
+ gem "appraisal"
7
+ gem "activerecord-jdbcsqlite3-adapter", platforms: :jruby
8
+ gem "sqlite3", platforms: [:ruby, :mswin, :mingw, :x64_mingw]
9
+ gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
10
+ gem "rspec-rails", "~> 3.7"
11
+
12
+ gemspec path: "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", git: 'https://github.com/rails/rails'
6
+ gem "arel", git: 'https://github.com/rails/arel'
7
+
8
+ gem "appraisal"
9
+ gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
10
+ gem "sqlite3", platform: [:ruby, :mswin, :mingw, :x64_mingw]
11
+ gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
12
+ gem "rspec-rails", "~> 3.7"
13
+
14
+ gemspec path: "../"
@@ -59,12 +59,12 @@ doorkeeper.
59
59
  # @option opts[Boolean] :confirmation (false)
60
60
  # Set confirm_application_owner variable
61
61
  def enable_application_owner(opts = {})
62
- @config.instance_variable_set('@enable_application_owner', true)
62
+ @config.instance_variable_set(:@enable_application_owner, true)
63
63
  confirm_application_owner if opts[:confirmation].present? && opts[:confirmation]
64
64
  end
65
65
 
66
66
  def confirm_application_owner
67
- @config.instance_variable_set('@confirm_application_owner', true)
67
+ @config.instance_variable_set(:@confirm_application_owner, true)
68
68
  end
69
69
 
70
70
  # Define default access token scopes for your provider
@@ -72,7 +72,7 @@ doorkeeper.
72
72
  # @param scopes [Array] Default set of access (OAuth::Scopes.new)
73
73
  # token scopes
74
74
  def default_scopes(*scopes)
75
- @config.instance_variable_set('@default_scopes', OAuth::Scopes.from_array(scopes))
75
+ @config.instance_variable_set(:@default_scopes, OAuth::Scopes.from_array(scopes))
76
76
  end
77
77
 
78
78
  # Define default access token scopes for your provider
@@ -80,7 +80,7 @@ doorkeeper.
80
80
  # @param scopes [Array] Optional set of access (OAuth::Scopes.new)
81
81
  # token scopes
82
82
  def optional_scopes(*scopes)
83
- @config.instance_variable_set('@optional_scopes', OAuth::Scopes.from_array(scopes))
83
+ @config.instance_variable_set(:@optional_scopes, OAuth::Scopes.from_array(scopes))
84
84
  end
85
85
 
86
86
  # Change the way client credentials are retrieved from the request object.
@@ -90,7 +90,7 @@ doorkeeper.
90
90
  #
91
91
  # @param methods [Array] Define client credentials
92
92
  def client_credentials(*methods)
93
- @config.instance_variable_set('@client_credentials', methods)
93
+ @config.instance_variable_set(:@client_credentials, methods)
94
94
  end
95
95
 
96
96
  # Change the way access token is authenticated from the request object.
@@ -100,57 +100,19 @@ doorkeeper.
100
100
  #
101
101
  # @param methods [Array] Define access token methods
102
102
  def access_token_methods(*methods)
103
- @config.instance_variable_set('@access_token_methods', methods)
103
+ @config.instance_variable_set(:@access_token_methods, methods)
104
104
  end
105
105
 
106
106
  # Issue access tokens with refresh token (disabled by default)
107
107
  def use_refresh_token
108
- @config.instance_variable_set('@refresh_token_enabled', true)
109
- end
110
-
111
- # WWW-Authenticate Realm (default "Doorkeeper").
112
- #
113
- # @param realm [String] ("Doorkeeper") Authentication realm
114
- def realm(realm)
115
- @config.instance_variable_set('@realm', realm)
108
+ @config.instance_variable_set(:@refresh_token_enabled, true)
116
109
  end
117
110
 
118
111
  # Reuse access token for the same resource owner within an application
119
112
  # (disabled by default)
120
113
  # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
121
114
  def reuse_access_token
122
- @config.instance_variable_set("@reuse_access_token", true)
123
- end
124
-
125
- # Forces the usage of the HTTPS protocol in non-native redirect uris
126
- # (enabled by default in non-development environments). OAuth2
127
- # delegates security in communication to the HTTPS protocol so it is
128
- # wise to keep this enabled.
129
- #
130
- # @param [Boolean] boolean value for the parameter, true by default in
131
- # non-development environment
132
- def force_ssl_in_redirect_uri(boolean)
133
- @config.instance_variable_set("@force_ssl_in_redirect_uri", boolean)
134
- end
135
-
136
- # Use a custom class for generating the access token.
137
- # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
138
- #
139
- # @param access_token_generator [String]
140
- # the name of the access token generator class
141
- def access_token_generator(access_token_generator)
142
- @config.instance_variable_set(
143
- '@access_token_generator', access_token_generator
144
- )
145
- end
146
-
147
- # The controller Doorkeeper::ApplicationController inherits from.
148
- # Defaults to ActionController::Base.
149
- # https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
150
- #
151
- # @param base_controller [String] the name of the base controller
152
- def base_controller(base_controller)
153
- @config.instance_variable_set('@base_controller', base_controller)
115
+ @config.instance_variable_set(:@reuse_access_token, true)
154
116
  end
155
117
  end
156
118
 
@@ -210,10 +172,6 @@ doorkeeper.
210
172
 
211
173
  public attribute
212
174
  end
213
-
214
- def extended(base)
215
- base.send(:private, :option)
216
- end
217
175
  end
218
176
 
219
177
  extend Option
@@ -221,15 +179,17 @@ doorkeeper.
221
179
  option :resource_owner_authenticator,
222
180
  as: :authenticate_resource_owner,
223
181
  default: (lambda do |_routes|
224
- logger.warn(I18n.translate('doorkeeper.errors.messages.resource_owner_authenticator_not_configured'))
182
+ ::Rails.logger.warn(I18n.t('doorkeeper.errors.messages.resource_owner_authenticator_not_configured'))
225
183
  nil
226
184
  end)
185
+
227
186
  option :admin_authenticator,
228
187
  as: :authenticate_admin,
229
188
  default: ->(_routes) {}
189
+
230
190
  option :resource_owner_from_credentials,
231
191
  default: (lambda do |_routes|
232
- warn(I18n.translate('doorkeeper.errors.messages.credential_flow_not_configured'))
192
+ ::Rails.logger.warn(I18n.t('doorkeeper.errors.messages.credential_flow_not_configured'))
233
193
  nil
234
194
  end)
235
195
 
@@ -240,11 +200,51 @@ doorkeeper.
240
200
  option :orm, default: :active_record
241
201
  option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
242
202
  option :active_record_options, default: {}
203
+ option :grant_flows, default: %w[authorization_code client_credentials]
204
+
205
+ # Allows to forbid specific Application redirect URI's by custom rules.
206
+ # Doesn't forbid any URI by default.
207
+ #
208
+ # @param forbid_redirect_uri [Proc] Block or any object respond to #call
209
+ #
210
+ option :forbid_redirect_uri, default: ->(_uri) { false }
211
+
212
+ # WWW-Authenticate Realm (default "Doorkeeper").
213
+ #
214
+ # @param realm [String] ("Doorkeeper") Authentication realm
215
+ #
243
216
  option :realm, default: 'Doorkeeper'
217
+
218
+ # Forces the usage of the HTTPS protocol in non-native redirect uris
219
+ # (enabled by default in non-development environments). OAuth2
220
+ # delegates security in communication to the HTTPS protocol so it is
221
+ # wise to keep this enabled.
222
+ #
223
+ # @param [Boolean] boolean_or_block value for the parameter, true by default in
224
+ # non-development environment
225
+ #
226
+ # @yield [uri] Conditional usage of SSL redirect uris.
227
+ # @yieldparam [URI] Redirect URI
228
+ # @yieldreturn [Boolean] Indicates necessity of usage of the HTTPS protocol
229
+ # in non-native redirect uris
230
+ #
244
231
  option :force_ssl_in_redirect_uri, default: !Rails.env.development?
245
- option :grant_flows, default: %w(authorization_code client_credentials)
232
+
233
+
234
+ # Use a custom class for generating the access token.
235
+ # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
236
+ #
237
+ # @param access_token_generator [String]
238
+ # the name of the access token generator class
239
+ #
246
240
  option :access_token_generator,
247
241
  default: 'Doorkeeper::OAuth::Helpers::UniqueToken'
242
+
243
+ # The controller Doorkeeper::ApplicationController inherits from.
244
+ # Defaults to ActionController::Base.
245
+ # https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
246
+ #
247
+ # @param base_controller [String] the name of the base controller
248
248
  option :base_controller,
249
249
  default: 'ActionController::Base'
250
250
 
@@ -278,11 +278,11 @@ doorkeeper.
278
278
  end
279
279
 
280
280
  def client_credentials_methods
281
- @client_credentials ||= [:from_basic, :from_params]
281
+ @client_credentials ||= %i[from_basic from_params]
282
282
  end
283
283
 
284
284
  def access_token_methods
285
- @access_token_methods ||= [:from_bearer_authorization, :from_access_token_param, :from_bearer_param]
285
+ @access_token_methods ||= %i[from_bearer_authorization from_access_token_param from_bearer_param]
286
286
  end
287
287
 
288
288
  def authorization_response_types
@@ -1,7 +1,7 @@
1
1
  module Doorkeeper
2
2
  class Engine < Rails::Engine
3
3
  initializer "doorkeeper.params.filter" do |app|
4
- parameters = %w(client_secret code authentication_token access_token refresh_token)
4
+ parameters = %w[client_secret code authentication_token access_token refresh_token]
5
5
  app.config.filter_parameters << /^(#{Regexp.union parameters})$/
6
6
  end
7
7
 
@@ -17,10 +17,10 @@ module Doorkeeper
17
17
 
18
18
  if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
19
19
  initializer 'doorkeeper.assets.precompile' do |app|
20
- app.config.assets.precompile += %w(
20
+ app.config.assets.precompile += %w[
21
21
  doorkeeper/application.css
22
22
  doorkeeper/admin/application.css
23
- )
23
+ ]
24
24
  end
25
25
  end
26
26
  end
@@ -1,21 +1,39 @@
1
1
  module Doorkeeper
2
2
  module Errors
3
3
  class DoorkeeperError < StandardError
4
+ def type
5
+ message
6
+ end
4
7
  end
5
8
 
6
9
  class InvalidAuthorizationStrategy < DoorkeeperError
10
+ def type
11
+ :unsupported_response_type
12
+ end
7
13
  end
8
14
 
9
15
  class InvalidTokenReuse < DoorkeeperError
16
+ def type
17
+ :invalid_request
18
+ end
10
19
  end
11
20
 
12
21
  class InvalidGrantReuse < DoorkeeperError
22
+ def type
23
+ :invalid_grant
24
+ end
13
25
  end
14
26
 
15
27
  class InvalidTokenStrategy < DoorkeeperError
28
+ def type
29
+ :unsupported_grant_type
30
+ end
16
31
  end
17
32
 
18
33
  class MissingRequestStrategy < DoorkeeperError
34
+ def type
35
+ :invalid_request
36
+ end
19
37
  end
20
38
 
21
39
  class UnableToGenerateToken < DoorkeeperError
@@ -9,7 +9,7 @@ module Doorkeeper
9
9
 
10
10
  # endpoint specific scopes > parameter scopes > default scopes
11
11
  def doorkeeper_authorize!(*scopes)
12
- endpoint_scopes = env["api.endpoint"].route_setting(:scopes)
12
+ endpoint_scopes = endpoint.route_setting(:scopes) || endpoint.options[:route_options][:scopes]
13
13
  scopes = if endpoint_scopes
14
14
  Doorkeeper::OAuth::Scopes.from_array(endpoint_scopes)
15
15
  elsif scopes && !scopes.empty?
@@ -20,18 +20,16 @@ module Doorkeeper
20
20
  end
21
21
 
22
22
  def doorkeeper_render_error_with(error)
23
- status_code = case error.status
24
- when :unauthorized
25
- 401
26
- when :forbidden
27
- 403
28
- end
29
-
23
+ status_code = error_status_codes[error.status]
30
24
  error!({ error: error.description }, status_code, error.headers)
31
25
  end
32
26
 
33
27
  private
34
28
 
29
+ def endpoint
30
+ env['api.endpoint']
31
+ end
32
+
35
33
  def doorkeeper_token
36
34
  @_doorkeeper_token ||= OAuth::Token.authenticate(
37
35
  decorated_request,
@@ -42,6 +40,13 @@ module Doorkeeper
42
40
  def decorated_request
43
41
  AuthorizationDecorator.new(request)
44
42
  end
43
+
44
+ def error_status_codes
45
+ {
46
+ unauthorized: 401,
47
+ forbidden: 403
48
+ }
49
+ end
45
50
  end
46
51
  end
47
52
  end
@@ -5,11 +5,13 @@ module Doorkeeper
5
5
  module Controller
6
6
  private
7
7
 
8
- def authenticate_resource_owner! # :doc:
8
+ # :doc:
9
+ def authenticate_resource_owner!
9
10
  current_resource_owner
10
11
  end
11
12
 
12
- def current_resource_owner # :doc:
13
+ # :doc:
14
+ def current_resource_owner
13
15
  instance_eval(&Doorkeeper.configuration.authenticate_resource_owner)
14
16
  end
15
17
 
@@ -17,7 +19,8 @@ module Doorkeeper
17
19
  instance_eval(&Doorkeeper.configuration.resource_owner_from_credentials)
18
20
  end
19
21
 
20
- def authenticate_admin! # :doc:
22
+ # :doc:
23
+ def authenticate_admin!
21
24
  instance_eval(&Doorkeeper.configuration.authenticate_admin)
22
25
  end
23
26
 
@@ -25,7 +28,8 @@ module Doorkeeper
25
28
  @server ||= Server.new(self)
26
29
  end
27
30
 
28
- def doorkeeper_token # :doc:
31
+ # :doc:
32
+ def doorkeeper_token
29
33
  @token ||= OAuth::Token.authenticate request, *config_methods
30
34
  end
31
35
 
@@ -34,22 +38,7 @@ module Doorkeeper
34
38
  end
35
39
 
36
40
  def get_error_response_from_exception(exception)
37
- error_name = case exception
38
- when Errors::InvalidTokenStrategy
39
- :unsupported_grant_type
40
- when Errors::InvalidAuthorizationStrategy
41
- :unsupported_response_type
42
- when Errors::MissingRequestStrategy
43
- :invalid_request
44
- when Errors::InvalidTokenReuse
45
- :invalid_request
46
- when Errors::InvalidGrantReuse
47
- :invalid_grant
48
- when Errors::DoorkeeperError
49
- exception.message
50
- end
51
-
52
- OAuth::ErrorResponse.new name: error_name, state: params[:state]
41
+ OAuth::ErrorResponse.new name: exception.type, state: params[:state]
53
42
  end
54
43
 
55
44
  def handle_token_exception(exception)
@@ -68,11 +68,11 @@ module Doorkeeper
68
68
  # @param resource_owner [ActiveRecord::Base]
69
69
  # instance of the Resource Owner model
70
70
  #
71
- def revoke_all_for(application_id, resource_owner)
71
+ def revoke_all_for(application_id, resource_owner, clock = Time)
72
72
  where(application_id: application_id,
73
73
  resource_owner_id: resource_owner.id,
74
74
  revoked_at: nil).
75
- each(&:revoke)
75
+ update_all(revoked_at: clock.now.utc)
76
76
  end
77
77
 
78
78
  # Looking for not expired Access Token with a matching set of scopes
@@ -168,7 +168,7 @@ module Doorkeeper
168
168
  # nil if nothing was found
169
169
  #
170
170
  def last_authorized_token_for(application_id, resource_owner_id)
171
- send(order_method, created_at_desc).
171
+ ordered_by(:created_at, :desc).
172
172
  find_by(application_id: application_id,
173
173
  resource_owner_id: resource_owner_id,
174
174
  revoked_at: nil)
@@ -247,7 +247,11 @@ module Doorkeeper
247
247
  def generate_token
248
248
  self.created_at ||= Time.now.utc
249
249
 
250
- generator = Doorkeeper.configuration.access_token_generator.constantize
250
+ generator = token_generator
251
+ unless generator.respond_to?(:generate)
252
+ raise Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`."
253
+ end
254
+
251
255
  self.token = generator.generate(
252
256
  resource_owner_id: resource_owner_id,
253
257
  scopes: scopes,
@@ -255,10 +259,13 @@ module Doorkeeper
255
259
  expires_in: expires_in,
256
260
  created_at: created_at
257
261
  )
258
- rescue NoMethodError
259
- raise Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`."
262
+ end
263
+
264
+ def token_generator
265
+ generator_name = Doorkeeper.configuration.access_token_generator
266
+ generator_name.constantize
260
267
  rescue NameError
261
- raise Errors::TokenGeneratorNotFound, "#{generator} not found"
268
+ raise Errors::TokenGeneratorNotFound, "#{generator_name} not found"
262
269
  end
263
270
  end
264
271
  end
@@ -43,6 +43,15 @@ module Doorkeeper
43
43
  end
44
44
  end
45
45
 
46
+ # Set an application's valid redirect URIs.
47
+ #
48
+ # @param uris [String, Array] Newline-separated string or array the URI(s)
49
+ #
50
+ # @return [String] The redirect URI(s) seperated by newlines.
51
+ def redirect_uri=(uris)
52
+ super(uris.is_a?(Array) ? uris.join("\n") : uris)
53
+ end
54
+
46
55
  private
47
56
 
48
57
  def has_scopes?
@@ -51,15 +60,11 @@ module Doorkeeper
51
60
  end
52
61
 
53
62
  def generate_uid
54
- if uid.blank?
55
- self.uid = UniqueToken.generate
56
- end
63
+ self.uid = UniqueToken.generate if uid.blank?
57
64
  end
58
65
 
59
66
  def generate_secret
60
- if secret.blank?
61
- self.secret = UniqueToken.generate
62
- end
67
+ self.secret = UniqueToken.generate if secret.blank?
63
68
  end
64
69
  end
65
70
  end
@@ -6,7 +6,7 @@ module Doorkeeper
6
6
  #
7
7
  # @return [Boolean] true if object expired and false in other case
8
8
  def expired?
9
- expires_in && Time.now.utc > expired_time
9
+ expires_in && Time.now.utc > expires_at
10
10
  end
11
11
 
12
12
  # Calculates expiration time in seconds.
@@ -15,14 +15,16 @@ module Doorkeeper
15
15
  # or nil if object never expires.
16
16
  def expires_in_seconds
17
17
  return nil if expires_in.nil?
18
- expires = (created_at + expires_in.seconds) - Time.now.utc
18
+ expires = expires_at - Time.now.utc
19
19
  expires_sec = expires.seconds.round(0)
20
20
  expires_sec > 0 ? expires_sec : 0
21
21
  end
22
22
 
23
- private
24
-
25
- def expired_time
23
+ # Expiration time (date time of creation + TTL).
24
+ #
25
+ # @return [Time] expiration time in UTC
26
+ #
27
+ def expires_at
26
28
  created_at + expires_in.seconds
27
29
  end
28
30
  end
@@ -4,19 +4,33 @@ module Doorkeeper
4
4
  class Token
5
5
  attr_accessor :pre_auth, :resource_owner, :token
6
6
 
7
+ class << self
8
+ def access_token_expires_in(server, pre_auth_or_oauth_client)
9
+ if (expiration = custom_expiration(server, pre_auth_or_oauth_client))
10
+ expiration
11
+ else
12
+ server.access_token_expires_in
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def custom_expiration(server, pre_auth_or_oauth_client)
19
+ oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
20
+ pre_auth_or_oauth_client.client
21
+ else
22
+ pre_auth_or_oauth_client
23
+ end
24
+
25
+ server.custom_access_token_expires_in.call(oauth_client)
26
+ end
27
+ end
28
+
7
29
  def initialize(pre_auth, resource_owner)
8
30
  @pre_auth = pre_auth
9
31
  @resource_owner = resource_owner
10
32
  end
11
33
 
12
- def self.access_token_expires_in(server, pre_auth_or_oauth_client)
13
- if expiration = custom_expiration(server, pre_auth_or_oauth_client)
14
- expiration
15
- else
16
- server.access_token_expires_in
17
- end
18
- end
19
-
20
34
  def issue_token
21
35
  @token ||= AccessToken.find_or_create_for(
22
36
  pre_auth.client,
@@ -37,16 +51,6 @@ module Doorkeeper
37
51
 
38
52
  private
39
53
 
40
- def self.custom_expiration(server, pre_auth_or_oauth_client)
41
- oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
42
- pre_auth_or_oauth_client.client
43
- else
44
- pre_auth_or_oauth_client
45
- end
46
-
47
- server.custom_access_token_expires_in.call(oauth_client)
48
- end
49
-
50
54
  def configuration
51
55
  Doorkeeper.configuration
52
56
  end
@@ -4,6 +4,7 @@ module Doorkeeper
4
4
  validate :attributes, error: :invalid_request
5
5
  validate :client, error: :invalid_client
6
6
  validate :grant, error: :invalid_grant
7
+ # @see https://tools.ietf.org/html/rfc6749#section-5.2
7
8
  validate :redirect_uri, error: :invalid_grant
8
9
 
9
10
  attr_accessor :server, :grant, :client, :redirect_uri, :access_token
@@ -28,6 +29,7 @@ module Doorkeeper
28
29
  grant.scopes,
29
30
  server)
30
31
  end
32
+ super
31
33
  end
32
34
 
33
35
  def validate_attributes
@@ -44,7 +46,10 @@ module Doorkeeper
44
46
  end
45
47
 
46
48
  def validate_redirect_uri
47
- grant.redirect_uri == redirect_uri
49
+ Helpers::URIChecker.valid_for_authorization?(
50
+ redirect_uri,
51
+ grant.redirect_uri
52
+ )
48
53
  end
49
54
  end
50
55
  end
@@ -5,6 +5,7 @@ module Doorkeeper
5
5
 
6
6
  def authorize
7
7
  validate
8
+
8
9
  if valid?
9
10
  before_successful_response
10
11
  @response = TokenResponse.new(access_token)
@@ -37,14 +38,13 @@ module Doorkeeper
37
38
  resource_owner_id,
38
39
  scopes,
39
40
  Authorization::Token.access_token_expires_in(server, client),
40
- server.refresh_token_enabled?)
41
+ server.refresh_token_enabled?
42
+ )
41
43
  end
42
44
 
43
- def before_successful_response
44
- end
45
+ def before_successful_response; end
45
46
 
46
- def after_successful_response
47
- end
47
+ def after_successful_response; end
48
48
  end
49
49
  end
50
50
  end
@@ -1,7 +1,7 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
3
  class Client
4
- class Credentials < Struct.new(:uid, :secret)
4
+ Credentials = Struct.new(:uid, :secret) do
5
5
  class << self
6
6
  def from_request(request, *credentials_methods)
7
7
  credentials_methods.inject(nil) do |credentials, method|
@@ -18,7 +18,7 @@ module Doorkeeper
18
18
  def from_basic(request)
19
19
  authorization = request.authorization
20
20
  if authorization.present? && authorization =~ /^Basic (.*)/m
21
- Base64.decode64($1).split(/:/, 2)
21
+ Base64.decode64(Regexp.last_match(1)).split(/:/, 2)
22
22
  end
23
23
  end
24
24
  end