doorkeeper 5.1.2 → 5.2.0.rc1

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +812 -0
  3. data/CONTRIBUTING.md +4 -9
  4. data/Dangerfile +1 -1
  5. data/Gemfile +2 -1
  6. data/NEWS.md +1 -819
  7. data/README.md +2 -2
  8. data/RELEASING.md +6 -5
  9. data/app/controllers/doorkeeper/applications_controller.rb +5 -3
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  11. data/app/controllers/doorkeeper/tokens_controller.rb +18 -8
  12. data/app/validators/redirect_uri_validator.rb +19 -9
  13. data/app/views/doorkeeper/applications/_form.html.erb +0 -6
  14. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  15. data/config/locales/en.yml +3 -1
  16. data/doorkeeper.gemspec +1 -1
  17. data/gemfiles/rails_5_0.gemfile +1 -0
  18. data/gemfiles/rails_5_1.gemfile +1 -0
  19. data/gemfiles/rails_5_2.gemfile +1 -0
  20. data/gemfiles/rails_6_0.gemfile +2 -1
  21. data/gemfiles/rails_master.gemfile +1 -0
  22. data/lib/doorkeeper.rb +3 -0
  23. data/lib/doorkeeper/config.rb +30 -3
  24. data/lib/doorkeeper/config/option.rb +13 -7
  25. data/lib/doorkeeper/grape/helpers.rb +5 -1
  26. data/lib/doorkeeper/helpers/controller.rb +16 -3
  27. data/lib/doorkeeper/oauth/authorization/code.rb +10 -8
  28. data/lib/doorkeeper/oauth/authorization/token.rb +1 -1
  29. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  30. data/lib/doorkeeper/oauth/error_response.rb +1 -1
  31. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +18 -4
  32. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  33. data/lib/doorkeeper/oauth/refresh_token_request.rb +8 -8
  34. data/lib/doorkeeper/oauth/token_introspection.rb +13 -12
  35. data/lib/doorkeeper/orm/active_record.rb +17 -1
  36. data/lib/doorkeeper/orm/active_record/access_grant.rb +1 -1
  37. data/lib/doorkeeper/orm/active_record/access_token.rb +2 -2
  38. data/lib/doorkeeper/orm/active_record/application.rb +5 -65
  39. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  40. data/lib/doorkeeper/version.rb +3 -3
  41. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +6 -6
  42. data/lib/generators/doorkeeper/templates/initializer.rb +41 -9
  43. data/lib/generators/doorkeeper/templates/migration.rb.erb +3 -0
  44. data/spec/controllers/applications_controller_spec.rb +93 -0
  45. data/spec/controllers/protected_resources_controller_spec.rb +3 -3
  46. data/spec/controllers/tokens_controller_spec.rb +71 -3
  47. data/spec/dummy/config/application.rb +3 -1
  48. data/spec/dummy/config/initializers/doorkeeper.rb +27 -9
  49. data/spec/lib/config_spec.rb +11 -0
  50. data/spec/lib/oauth/helpers/uri_checker_spec.rb +17 -2
  51. data/spec/lib/oauth/pre_authorization_spec.rb +0 -15
  52. data/spec/models/doorkeeper/application_spec.rb +268 -373
  53. data/spec/requests/flows/authorization_code_spec.rb +16 -4
  54. data/spec/requests/flows/revoke_token_spec.rb +19 -11
  55. data/spec/support/doorkeeper_rspec.rb +1 -1
  56. data/spec/validators/redirect_uri_validator_spec.rb +39 -14
  57. metadata +7 -15
  58. data/.coveralls.yml +0 -1
  59. data/.github/ISSUE_TEMPLATE.md +0 -25
  60. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  61. data/.gitignore +0 -20
  62. data/.gitlab-ci.yml +0 -16
  63. data/.hound.yml +0 -3
  64. data/.rspec +0 -1
  65. data/.rubocop.yml +0 -50
  66. data/.travis.yml +0 -35
data/README.md CHANGED
@@ -146,10 +146,10 @@ bundle exec rake doorkeeper:server
146
146
  ````
147
147
 
148
148
  By default, it uses the latest Rails version with ActiveRecord. To run the
149
- tests with a specific ORM and Rails version:
149
+ tests with a specific Rails version:
150
150
 
151
151
  ```
152
- rails=5.2 orm=active_record bundle exec rake
152
+ BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle exec rake
153
153
  ```
154
154
 
155
155
  ## Contributing
@@ -1,10 +1,11 @@
1
- # Releasing doorkeeper
1
+ # Releasing Doorkeeper
2
2
 
3
- How to release doorkeeper in five easy steps!
3
+ How to release Doorkeeper in five easy steps!
4
4
 
5
5
  1. Update `lib/doorkeeper/version.rb` file accordingly.
6
- 2. Update `NEWS.md` to reflect the changes since last release.
7
- 3. Commit changes: `git commit -am 'Bump to vVERSION'`
8
- 4. Run `rake release`
6
+ 2. Update `CHANGELOG.md` to reflect the changes since last release.
7
+ 3. Commit changes: `git commit -am 'Bump to vVERSION'`.
8
+ 4. Build and publish the gem.
9
+ 4. Create GitHub release.
9
10
  5. Announce the new release, making sure to say “thank you” to the contributors
10
11
  who helped shape this version!
@@ -4,6 +4,7 @@ module Doorkeeper
4
4
  class ApplicationsController < Doorkeeper::ApplicationController
5
5
  layout "doorkeeper/admin" unless Doorkeeper.configuration.api_only
6
6
 
7
+ add_flash_types :application_secret
7
8
  before_action :authenticate_admin!
8
9
  before_action :set_application, only: %i[show edit update destroy]
9
10
 
@@ -19,7 +20,7 @@ module Doorkeeper
19
20
  def show
20
21
  respond_to do |format|
21
22
  format.html
22
- format.json { render json: @application, as_owner: true }
23
+ format.json { render json: @application }
23
24
  end
24
25
  end
25
26
 
@@ -32,10 +33,11 @@ module Doorkeeper
32
33
 
33
34
  if @application.save
34
35
  flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications create])
36
+ flash[:application_secret] = @application.plaintext_secret
35
37
 
36
38
  respond_to do |format|
37
39
  format.html { redirect_to oauth_application_url(@application) }
38
- format.json { render json: @application, as_owner: true }
40
+ format.json { render json: @application }
39
41
  end
40
42
  else
41
43
  respond_to do |format|
@@ -57,7 +59,7 @@ module Doorkeeper
57
59
 
58
60
  respond_to do |format|
59
61
  format.html { redirect_to oauth_application_url(@application) }
60
- format.json { render json: @application, as_owner: true }
62
+ format.json { render json: @application }
61
63
  end
62
64
  else
63
65
  respond_to do |format|
@@ -9,7 +9,7 @@ module Doorkeeper
9
9
 
10
10
  respond_to do |format|
11
11
  format.html
12
- format.json { render json: @applications, current_resource_owner: current_resource_owner }
12
+ format.json { render json: @applications }
13
13
  end
14
14
  end
15
15
 
@@ -6,8 +6,8 @@ module Doorkeeper
6
6
  headers.merge!(authorize_response.headers)
7
7
  render json: authorize_response.body,
8
8
  status: authorize_response.status
9
- rescue Errors::DoorkeeperError => error
10
- handle_token_exception(error)
9
+ rescue Errors::DoorkeeperError => e
10
+ handle_token_exception(e)
11
11
  end
12
12
 
13
13
  # OAuth 2.0 Token Revocation - http://tools.ietf.org/html/rfc7009
@@ -18,12 +18,13 @@ module Doorkeeper
18
18
  # Doorkeeper does not use the token_type_hint logic described in the
19
19
  # RFC 7009 due to the refresh token implementation that is a field in
20
20
  # the access token model.
21
- revoke_token if authorized?
22
21
 
23
- # The authorization server responds with HTTP status code 200 if the token
24
- # has been revoked successfully or if the client submitted an invalid
25
- # token
26
- render json: {}, status: 200
22
+ if authorized?
23
+ revoke_token
24
+ render json: {}, status: 200
25
+ else
26
+ render json: revocation_error_response, status: :forbidden
27
+ end
27
28
  end
28
29
 
29
30
  def introspect
@@ -71,7 +72,10 @@ module Doorkeeper
71
72
  end
72
73
 
73
74
  def revoke_token
74
- token.revoke if token.accessible?
75
+ # The authorization server responds with HTTP status code 200 if the token
76
+ # has been revoked successfully or if the client submitted an invalid
77
+ # token
78
+ token.revoke if token&.accessible?
75
79
  end
76
80
 
77
81
  def token
@@ -86,5 +90,11 @@ module Doorkeeper
86
90
  def authorize_response
87
91
  @authorize_response ||= strategy.authorize
88
92
  end
93
+
94
+ def revocation_error_response
95
+ error_description = I18n.t(:unauthorized, scope: %i[doorkeeper errors messages revoke])
96
+
97
+ { error: :unauthorized_client, error_description: error_description }
98
+ end
89
99
  end
90
100
  end
@@ -2,11 +2,10 @@
2
2
 
3
3
  require "uri"
4
4
 
5
+ # ActiveModel validator for redirect URI validation in according
6
+ # to OAuth standards and Doorkeeper configuration.
7
+ #
5
8
  class RedirectUriValidator < ActiveModel::EachValidator
6
- def self.native_redirect_uri
7
- Doorkeeper.configuration.native_redirect_uri
8
- end
9
-
10
9
  def validate_each(record, attribute, value)
11
10
  if value.blank?
12
11
  return if Doorkeeper.configuration.allow_blank_redirect_uri?(record)
@@ -14,12 +13,13 @@ class RedirectUriValidator < ActiveModel::EachValidator
14
13
  record.errors.add(attribute, :blank)
15
14
  else
16
15
  value.split.each do |val|
17
- uri = ::URI.parse(val)
18
- next if native_redirect_uri?(uri)
16
+ next if oob_redirect_uri?(val)
19
17
 
18
+ uri = ::URI.parse(val)
20
19
  record.errors.add(attribute, :forbidden_uri) if forbidden_uri?(uri)
21
20
  record.errors.add(attribute, :fragment_present) unless uri.fragment.nil?
22
- record.errors.add(attribute, :relative_uri) if uri.scheme.nil? || uri.host.nil?
21
+ record.errors.add(attribute, :unspecified_scheme) if unspecified_scheme?(uri)
22
+ record.errors.add(attribute, :relative_uri) if relative_uri?(uri)
23
23
  record.errors.add(attribute, :secured_uri) if invalid_ssl_uri?(uri)
24
24
  end
25
25
  end
@@ -29,14 +29,24 @@ class RedirectUriValidator < ActiveModel::EachValidator
29
29
 
30
30
  private
31
31
 
32
- def native_redirect_uri?(uri)
33
- self.class.native_redirect_uri.present? && uri.to_s == self.class.native_redirect_uri.to_s
32
+ def oob_redirect_uri?(uri)
33
+ Doorkeeper::OAuth::NonStandard::IETF_WG_OAUTH2_OOB_METHODS.include?(uri)
34
34
  end
35
35
 
36
36
  def forbidden_uri?(uri)
37
37
  Doorkeeper.configuration.forbid_redirect_uri.call(uri)
38
38
  end
39
39
 
40
+ def unspecified_scheme?(uri)
41
+ return true if uri.opaque.present?
42
+
43
+ %w[localhost].include?(uri.try(:scheme))
44
+ end
45
+
46
+ def relative_uri?(uri)
47
+ uri.scheme.nil? && uri.host.nil?
48
+ end
49
+
40
50
  def invalid_ssl_uri?(uri)
41
51
  forces_ssl = Doorkeeper.configuration.force_ssl_in_redirect_uri
42
52
  non_https = uri.try(:scheme) == "http"
@@ -20,12 +20,6 @@
20
20
  <%= t('doorkeeper.applications.help.redirect_uri') %>
21
21
  </span>
22
22
 
23
- <% if Doorkeeper.configuration.native_redirect_uri %>
24
- <span class="form-text text-secondary">
25
- <%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, class: 'bg-light') { Doorkeeper.configuration.native_redirect_uri }) %>
26
- </span>
27
- <% end %>
28
-
29
23
  <% if Doorkeeper.configuration.allow_blank_redirect_uri?(application) %>
30
24
  <span class="form-text text-secondary">
31
25
  <%= t('doorkeeper.applications.help.blank_redirect_uri') %>
@@ -8,7 +8,7 @@
8
8
  <p><code class="bg-light" id="application_id"><%= @application.uid %></code></p>
9
9
 
10
10
  <h4><%= t('.secret') %>:</h4>
11
- <p><code class="bg-light" id="secret"><%= @application.plaintext_secret %></code></p>
11
+ <p><code class="bg-light" id="secret"><%= flash[:application_secret].presence || @application.plaintext_secret %></code></p>
12
12
 
13
13
  <h4><%= t('.scopes') %>:</h4>
14
14
  <p><code class="bg-light" id="scopes"><%= @application.scopes.presence || raw('&nbsp;') %></code></p>
@@ -11,6 +11,7 @@ en:
11
11
  redirect_uri:
12
12
  fragment_present: 'cannot contain a fragment.'
13
13
  invalid_uri: 'must be a valid URI.'
14
+ unspecified_scheme: 'must specify a scheme.'
14
15
  relative_uri: 'must be an absolute URI.'
15
16
  secured_uri: 'must be an HTTPS/SSL URI.'
16
17
  forbidden_uri: 'is forbidden by the server.'
@@ -33,7 +34,6 @@ en:
33
34
  confidential: 'Application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.'
34
35
  redirect_uri: 'Use one line per URI'
35
36
  blank_redirect_uri: "Leave it blank if you configured your provider to use Client Credentials, Resource Owner Password Credentials or any other grant type that doesn't require redirect URI."
36
- native_redirect_uri: 'Use %{native_redirect_uri} if you want to add localhost URIs for development purposes'
37
37
  scopes: 'Separate scopes with spaces. Leave blank to use the default scopes.'
38
38
  edit:
39
39
  title: 'Edit application'
@@ -114,6 +114,8 @@ en:
114
114
  revoked: "The access token was revoked"
115
115
  expired: "The access token expired"
116
116
  unknown: "The access token is invalid"
117
+ revoke:
118
+ unauthorized: "You are not authorized to revoke this token"
117
119
 
118
120
  flash:
119
121
  applications:
@@ -14,7 +14,7 @@ Gem::Specification.new do |gem|
14
14
  gem.description = "Doorkeeper is an OAuth 2 provider for Rails and Grape."
15
15
  gem.license = "MIT"
16
16
 
17
- gem.files = `git ls-files`.split("\n")
17
+ gem.files = `git ls-files`.split("\n").reject { |file| file.start_with?(".") }
18
18
  gem.test_files = `git ls-files -- spec/*`.split("\n")
19
19
  gem.require_paths = ["lib"]
20
20
 
@@ -9,6 +9,7 @@ gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
9
9
  gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
10
10
  gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
11
11
  gem "rubocop", "~> 0.66"
12
+ gem "rubocop-performance"
12
13
  gem "bcrypt", "~> 3.1", require: false
13
14
  gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
14
15
  gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
@@ -9,6 +9,7 @@ gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
9
9
  gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
10
10
  gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
11
11
  gem "rubocop", "~> 0.66"
12
+ gem "rubocop-performance"
12
13
  gem "bcrypt", "~> 3.1", require: false
13
14
  gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
14
15
  gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
@@ -9,6 +9,7 @@ gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
9
9
  gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
10
10
  gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
11
11
  gem "rubocop", "~> 0.66"
12
+ gem "rubocop-performance"
12
13
  gem "bcrypt", "~> 3.1", require: false
13
14
  gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
14
15
  gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
@@ -2,13 +2,14 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~> 6.0.0.beta3"
5
+ gem "rails", "~> 6.0.0.rc1"
6
6
  gem "rspec-core", git: "https://github.com/rspec/rspec-core.git"
7
7
  gem "rspec-expectations", git: "https://github.com/rspec/rspec-expectations.git"
8
8
  gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
9
9
  gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
10
10
  gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
11
11
  gem "rubocop", "~> 0.66"
12
+ gem "rubocop-performance"
12
13
  gem "bcrypt", "~> 3.1", require: false
13
14
  gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
14
15
  gem "sqlite3", "~> 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
@@ -9,6 +9,7 @@ gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
9
9
  gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
10
10
  gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
11
11
  gem "rubocop", "~> 0.66"
12
+ gem "rubocop-performance"
12
13
  gem "bcrypt", "~> 3.1", require: false
13
14
  gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
14
15
  gem "sqlite3", "~> 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
@@ -52,6 +52,7 @@ require "doorkeeper/oauth/token"
52
52
  require "doorkeeper/oauth/token_introspection"
53
53
  require "doorkeeper/oauth/invalid_token_response"
54
54
  require "doorkeeper/oauth/forbidden_token_response"
55
+ require "doorkeeper/oauth/nonstandard"
55
56
 
56
57
  require "doorkeeper/secret_storing/base"
57
58
  require "doorkeeper/secret_storing/plain"
@@ -80,6 +81,8 @@ require "doorkeeper/stale_records_cleaner"
80
81
 
81
82
  require "doorkeeper/orm/active_record"
82
83
 
84
+ # Main Doorkeeper namespace.
85
+ #
83
86
  module Doorkeeper
84
87
  def self.authenticate(request, methods = Doorkeeper.configuration.access_token_methods)
85
88
  OAuth::Token.authenticate(request, *methods)
@@ -25,8 +25,8 @@ module Doorkeeper
25
25
 
26
26
  def self.setup_orm_adapter
27
27
  @orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
28
- rescue NameError => error
29
- raise error, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
28
+ rescue NameError => e
29
+ raise e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
30
30
  [doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
31
31
  trying to load it.
32
32
 
@@ -254,7 +254,7 @@ module Doorkeeper
254
254
  option :custom_access_token_expires_in, default: ->(_context) { nil }
255
255
  option :authorization_code_expires_in, default: 600
256
256
  option :orm, default: :active_record
257
- option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob"
257
+ option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob", deprecated: true
258
258
  option :active_record_options, default: {}
259
259
  option :grant_flows, default: %w[authorization_code client_credentials]
260
260
  option :handle_auth_errors, default: :render
@@ -321,6 +321,33 @@ module Doorkeeper
321
321
  grant_flows.exclude?("implicit")
322
322
  end)
323
323
 
324
+ # Configure protection of token introspection request.
325
+ # By default token introspection is allowed only for clients that
326
+ # introspected token belongs to or if access token been introspected
327
+ # is a public one (doesn't belong to any client).
328
+ #
329
+ # You can define any custom rule you need or just disable token
330
+ # introspection at all.
331
+ #
332
+ # @param token [Doorkeeper::AccessToken]
333
+ # token to be introspected
334
+ #
335
+ # @param authorized_client [Doorkeeper::Application]
336
+ # authorized client (if request is authorized using Basic auth with
337
+ # Client Credentials for example)
338
+ #
339
+ # @param authorized_token [Doorkeeper::AccessToken]
340
+ # Bearer token used to authorize the request
341
+ #
342
+ option :allow_token_introspection,
343
+ default: (lambda do |token, authorized_client, _authorized_token|
344
+ if token.application
345
+ token.application == authorized_client
346
+ else
347
+ true
348
+ end
349
+ end)
350
+
324
351
  attr_reader :api_only,
325
352
  :enforce_content_type,
326
353
  :reuse_access_token,
@@ -38,14 +38,20 @@ module Doorkeeper
38
38
 
39
39
  Builder.instance_eval do
40
40
  remove_method name if method_defined?(name)
41
- define_method name do |*args, &block|
42
- value = if attribute_builder
43
- attribute_builder.new(&block).build
44
- else
45
- block || args.first
46
- end
41
+ if options[:deprecated]
42
+ define_method name do |*_, &_|
43
+ Kernel.warn "[DOORKEEPER] #{name} has been deprecated and will soon be removed"
44
+ end
45
+ else
46
+ define_method name do |*args, &block|
47
+ value = if attribute_builder
48
+ attribute_builder.new(&block).build
49
+ else
50
+ block || args.first
51
+ end
47
52
 
48
- @config.instance_variable_set(:"@#{attribute}", value)
53
+ @config.instance_variable_set(:"@#{attribute}", value)
54
+ end
49
55
  end
50
56
  end
51
57
 
@@ -4,6 +4,8 @@ require "doorkeeper/grape/authorization_decorator"
4
4
 
5
5
  module Doorkeeper
6
6
  module Grape
7
+ # Doorkeeper helpers for Grape applications.
8
+ # Provides helpers for endpoints authorization based on defined set of scopes.
7
9
  module Helpers
8
10
  # These helpers are for grape >= 0.10
9
11
  extend ::Grape::API::Helpers
@@ -11,7 +13,9 @@ module Doorkeeper
11
13
 
12
14
  # endpoint specific scopes > parameter scopes > default scopes
13
15
  def doorkeeper_authorize!(*scopes)
14
- endpoint_scopes = endpoint.route_setting(:scopes) || endpoint.options[:route_options][:scopes]
16
+ endpoint_scopes = endpoint.route_setting(:scopes) ||
17
+ endpoint.options[:route_options][:scopes]
18
+
15
19
  scopes = if endpoint_scopes
16
20
  Doorkeeper::OAuth::Scopes.from_array(endpoint_scopes)
17
21
  elsif scopes && !scopes.empty?
@@ -4,6 +4,8 @@
4
4
  # Doorkeeper::ApplicationMetalController or Doorkeeper::ApplicationController
5
5
  module Doorkeeper
6
6
  module Helpers
7
+ # Rails controller helpers.
8
+ #
7
9
  module Controller
8
10
  private
9
11
 
@@ -40,7 +42,11 @@ module Doorkeeper
40
42
  end
41
43
 
42
44
  def get_error_response_from_exception(exception)
43
- OAuth::ErrorResponse.new name: exception.type, state: params[:state]
45
+ if exception.respond_to?(:response)
46
+ exception.response
47
+ else
48
+ OAuth::ErrorResponse.new name: exception.type, state: params[:state]
49
+ end
44
50
  end
45
51
 
46
52
  def handle_token_exception(exception)
@@ -51,14 +57,21 @@ module Doorkeeper
51
57
  end
52
58
 
53
59
  def skip_authorization?
54
- !!instance_exec([@server.current_resource_owner, @pre_auth.client], &Doorkeeper.configuration.skip_authorization)
60
+ !!instance_exec(
61
+ [@server.current_resource_owner, @pre_auth.client],
62
+ &Doorkeeper.configuration.skip_authorization
63
+ )
55
64
  end
56
65
 
57
66
  def enforce_content_type
58
- if (request.put? || request.post? || request.patch?) && request.content_type != "application/x-www-form-urlencoded"
67
+ if (request.put? || request.post? || request.patch?) && !x_www_form_urlencoded?
59
68
  render json: {}, status: :unsupported_media_type
60
69
  end
61
70
  end
71
+
72
+ def x_www_form_urlencoded?
73
+ request.content_type == "application/x-www-form-urlencoded"
74
+ end
62
75
  end
63
76
  end
64
77
  end