doorkeeper 5.0.2 → 5.1.0.rc1

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 (63) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +7 -3
  3. data/Dangerfile +5 -2
  4. data/Gemfile +3 -1
  5. data/NEWS.md +18 -10
  6. data/README.md +1 -1
  7. data/app/controllers/doorkeeper/tokens_controller.rb +6 -6
  8. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  9. data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
  10. data/bin/console +15 -0
  11. data/gemfiles/rails_4_2.gemfile +1 -0
  12. data/gemfiles/rails_5_0.gemfile +1 -0
  13. data/gemfiles/rails_5_1.gemfile +1 -0
  14. data/gemfiles/rails_5_2.gemfile +2 -1
  15. data/gemfiles/rails_master.gemfile +1 -0
  16. data/lib/doorkeeper/config.rb +73 -6
  17. data/lib/doorkeeper/helpers/controller.rb +3 -2
  18. data/lib/doorkeeper/models/access_grant_mixin.rb +8 -1
  19. data/lib/doorkeeper/models/access_token_mixin.rb +40 -9
  20. data/lib/doorkeeper/models/application_mixin.rb +52 -1
  21. data/lib/doorkeeper/models/concerns/hashable.rb +137 -0
  22. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  23. data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
  24. data/lib/doorkeeper/oauth/authorization/token.rb +1 -1
  25. data/lib/doorkeeper/oauth/authorization_code_request.rb +1 -1
  26. data/lib/doorkeeper/oauth/client.rb +1 -1
  27. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -3
  28. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  29. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
  30. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +32 -0
  31. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  32. data/lib/doorkeeper/oauth/pre_authorization.rb +8 -3
  33. data/lib/doorkeeper/oauth/refresh_token_request.rb +4 -1
  34. data/lib/doorkeeper/oauth/token_response.rb +2 -2
  35. data/lib/doorkeeper/orm/active_record/access_grant.rb +22 -2
  36. data/lib/doorkeeper/orm/active_record/application.rb +16 -2
  37. data/lib/doorkeeper/version.rb +3 -3
  38. data/lib/doorkeeper.rb +1 -0
  39. data/lib/generators/doorkeeper/templates/initializer.rb +41 -1
  40. data/spec/controllers/application_metal_controller_spec.rb +18 -4
  41. data/spec/controllers/tokens_controller_spec.rb +7 -11
  42. data/spec/dummy/app/controllers/application_controller.rb +1 -1
  43. data/spec/factories.rb +3 -3
  44. data/spec/lib/config_spec.rb +84 -0
  45. data/spec/lib/models/hashable_spec.rb +183 -0
  46. data/spec/lib/oauth/base_request_spec.rb +7 -7
  47. data/spec/lib/oauth/client_credentials/validation_spec.rb +3 -0
  48. data/spec/lib/oauth/helpers/scope_checker_spec.rb +52 -17
  49. data/spec/lib/oauth/helpers/uri_checker_spec.rb +20 -2
  50. data/spec/lib/oauth/password_access_token_request_spec.rb +32 -11
  51. data/spec/lib/oauth/pre_authorization_spec.rb +24 -0
  52. data/spec/lib/oauth/token_response_spec.rb +13 -13
  53. data/spec/lib/oauth/token_spec.rb +14 -0
  54. data/spec/models/doorkeeper/access_grant_spec.rb +61 -0
  55. data/spec/models/doorkeeper/access_token_spec.rb +123 -0
  56. data/spec/models/doorkeeper/application_spec.rb +37 -0
  57. data/spec/requests/flows/authorization_code_spec.rb +40 -0
  58. data/spec/requests/flows/password_spec.rb +4 -2
  59. data/spec/requests/flows/revoke_token_spec.rb +14 -30
  60. data/spec/spec_helper.rb +2 -1
  61. data/spec/support/ruby_2_6_rails_4_2_patch.rb +14 -0
  62. data/spec/support/shared/hashing_shared_context.rb +29 -0
  63. metadata +13 -6
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ ##
6
+ # Hashable finder to provide lookups for input plaintext values which are
7
+ # mapped to their hashes before lookup.
8
+ module Hashable
9
+ extend ActiveSupport::Concern
10
+
11
+ delegate :perform_secret_hashing?,
12
+ :hashed_or_plain_token,
13
+ to: :class
14
+
15
+ # :nodoc
16
+ module ClassMethods
17
+ # Allow to override the hashing method by the including module
18
+ attr_accessor :secret_hash_function, :secret_comparer
19
+
20
+ # Compare the given plaintext with the secret
21
+ #
22
+ # @param input [String]
23
+ # The plain input to compare.
24
+ #
25
+ # @param secret [String]
26
+ # The secret value to compare with.
27
+ #
28
+ # @return [Boolean]
29
+ # If hashing is enabled: Whether the secret equals hashed input
30
+ # If hashing is disabled: Whether input matches secret
31
+ #
32
+ def secret_matches?(input, secret)
33
+ unless perform_secret_hashing?
34
+ return ActiveSupport::SecurityUtils.secure_compare input, secret
35
+ end
36
+
37
+ (secret_comparer || method(:default_comparer))
38
+ .call(input, secret)
39
+ end
40
+
41
+ # Returns an instance of the Doorkeeper::AccessToken with
42
+ # specific token value.
43
+ #
44
+ # @param attr [Symbol]
45
+ # The token attribute we're looking with.
46
+ #
47
+ # @param token [#to_s]
48
+ # token value (any object that responds to `#to_s`)
49
+ #
50
+ # @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
51
+ # if there is no record with such token
52
+ #
53
+ def find_by_plaintext_token(attr, token)
54
+ token = token.to_s
55
+
56
+ find_by(attr => hashed_or_plain_token(token)) ||
57
+ find_by_fallback_token(attr, token)
58
+ end
59
+
60
+ # Allow looking up previously plain tokens as a fallback
61
+ # IFF respective options are enabled
62
+ #
63
+ # @param attr [Symbol]
64
+ # The token attribute we're looking with.
65
+ #
66
+ # @param token [#to_s]
67
+ # token value (any object that responds to `#to_s`)
68
+ #
69
+ # @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
70
+ # if there is no record with such token
71
+ #
72
+ def find_by_fallback_token(attr, token)
73
+ return nil unless perform_secret_hashing?
74
+ return nil unless Doorkeeper.configuration.fallback_to_plain_secrets?
75
+
76
+ find_by(attr => token).tap do |fallback|
77
+ upgrade_fallback_value fallback, attr
78
+ end
79
+ end
80
+
81
+ # Hash the given input token
82
+ #
83
+ # @param plain_token [String]
84
+ # The plain text token to hash.
85
+ #
86
+ # @return [String]
87
+ # IFF secret hashing enabled, the hashed token,
88
+ # otherwise returns the plain token.
89
+ def hashed_or_plain_token(plain_token)
90
+ if perform_secret_hashing?
91
+ (secret_hash_function || method(:default_hash_function))
92
+ .call plain_token
93
+ else
94
+ plain_token
95
+ end
96
+ end
97
+
98
+ # Allow implementations in ORMs to replace a plain
99
+ # value falling back to to avoid it remaining as plain text.
100
+ #
101
+ # @param instance
102
+ # An instance of this model with a plain value token.
103
+ #
104
+ # @param attr
105
+ # The token attribute to upgrade
106
+ #
107
+ def upgrade_fallback_value(instance, attr)
108
+ plain_token = instance.public_send attr
109
+ instance.update_column(attr, hashed_or_plain_token(plain_token))
110
+ end
111
+
112
+ # Including classes can override this function to
113
+ # disable or enable secret hashing dynamically
114
+ def perform_secret_hashing?
115
+ true
116
+ end
117
+
118
+ # Return a default hashing function to be used when including
119
+ # module or user does not specify what to use
120
+ # @param plain_token [String]
121
+ # The plain text token to hash.
122
+ #
123
+ # @return [String] Hashed plain text token
124
+ #
125
+ def default_hash_function(plain_token)
126
+ ::Digest::SHA256.hexdigest plain_token
127
+ end
128
+
129
+ # Return a default comparer for the given hash function
130
+ def default_comparer(plain, secret)
131
+ hashed = hashed_or_plain_token(plain)
132
+ ActiveSupport::SecurityUtils.secure_compare hashed, secret
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -4,7 +4,7 @@ module Doorkeeper
4
4
  module Models
5
5
  module Scopes
6
6
  def scopes
7
- OAuth::Scopes.from_string(self[:scopes])
7
+ OAuth::Scopes.from_string(scopes_string)
8
8
  end
9
9
 
10
10
  def scopes_string
@@ -16,7 +16,7 @@ module Doorkeeper
16
16
  end
17
17
 
18
18
  def native_redirect
19
- { action: :show, code: token.token }
19
+ { action: :show, code: token.plaintext_token }
20
20
  end
21
21
 
22
22
  def configuration
@@ -62,7 +62,7 @@ module Doorkeeper
62
62
  {
63
63
  controller: controller,
64
64
  action: :show,
65
- access_token: token.token
65
+ access_token: token.plaintext_token
66
66
  }
67
67
  end
68
68
 
@@ -49,7 +49,7 @@ module Doorkeeper
49
49
  end
50
50
 
51
51
  def validate_client
52
- !client.nil?
52
+ client.present?
53
53
  end
54
54
 
55
55
  def validate_grant
@@ -18,7 +18,7 @@ module Doorkeeper
18
18
  end
19
19
 
20
20
  def self.authenticate(credentials, method = Application.method(:by_uid_and_secret))
21
- return false if credentials.blank?
21
+ return if credentials.blank?
22
22
 
23
23
  if (application = method.call(credentials.uid, credentials.secret))
24
24
  new(application)
@@ -34,9 +34,10 @@ module Doorkeeper
34
34
  end
35
35
 
36
36
  ScopeChecker.valid?(
37
- @request.scopes.to_s,
38
- @server.scopes,
39
- application_scopes
37
+ scope_str: @request.scopes.to_s,
38
+ server_scopes: @server.scopes,
39
+ app_scopes: application_scopes,
40
+ grant_type: Doorkeeper::OAuth::CLIENT_CREDENTIALS
40
41
  )
41
42
  end
42
43
  end
@@ -23,7 +23,7 @@ module Doorkeeper
23
23
  elsif response_on_fragment
24
24
  Authorization::URIBuilder.uri_with_fragment(
25
25
  pre_auth.redirect_uri,
26
- access_token: auth.token.token,
26
+ access_token: auth.token.plaintext_token,
27
27
  token_type: auth.token.token_type,
28
28
  expires_in: auth.token.expires_in_seconds,
29
29
  state: pre_auth.state
@@ -31,7 +31,7 @@ module Doorkeeper
31
31
  else
32
32
  Authorization::URIBuilder.uri_with_query(
33
33
  pre_auth.redirect_uri,
34
- code: auth.token.token,
34
+ code: auth.token.plaintext_token,
35
35
  state: pre_auth.state
36
36
  )
37
37
  end
@@ -7,31 +7,46 @@ module Doorkeeper
7
7
  class Validator
8
8
  attr_reader :parsed_scopes, :scope_str
9
9
 
10
- def initialize(scope_str, server_scopes, application_scopes)
10
+ def initialize(scope_str, server_scopes, app_scopes, grant_type)
11
11
  @parsed_scopes = OAuth::Scopes.from_string(scope_str)
12
12
  @scope_str = scope_str
13
- @valid_scopes = valid_scopes(server_scopes, application_scopes)
13
+ @valid_scopes = valid_scopes(server_scopes, app_scopes)
14
+
15
+ if grant_type
16
+ @scopes_by_grant_type = Doorkeeper.configuration.scopes_by_grant_type[grant_type.to_sym]
17
+ end
14
18
  end
15
19
 
16
20
  def valid?
17
21
  scope_str.present? &&
18
22
  scope_str !~ /[\n\r\t]/ &&
19
- @valid_scopes.has_scopes?(parsed_scopes)
23
+ @valid_scopes.has_scopes?(parsed_scopes) &&
24
+ permitted_to_grant_type?
20
25
  end
21
26
 
22
27
  private
23
28
 
24
- def valid_scopes(server_scopes, application_scopes)
25
- if application_scopes.present?
26
- application_scopes
29
+ def valid_scopes(server_scopes, app_scopes)
30
+ if app_scopes.present?
31
+ app_scopes
27
32
  else
28
33
  server_scopes
29
34
  end
30
35
  end
36
+
37
+ def permitted_to_grant_type?
38
+ return true unless @scopes_by_grant_type
39
+
40
+ OAuth::Scopes.from_array(@scopes_by_grant_type)
41
+ .has_scopes?(parsed_scopes)
42
+ end
31
43
  end
32
44
 
33
- def self.valid?(scope_str, server_scopes, application_scopes = nil)
34
- Validator.new(scope_str, server_scopes, application_scopes).valid?
45
+ def self.valid?(scope_str:, server_scopes:, app_scopes: nil, grant_type: nil)
46
+ Validator.new(scope_str,
47
+ server_scopes,
48
+ app_scopes,
49
+ grant_type).valid?
35
50
  end
36
51
  end
37
52
  end
@@ -1,6 +1,25 @@
1
1
  # frozen_string_literal: true
2
+ require 'ipaddr'
2
3
 
3
4
  module Doorkeeper
5
+ module IPAddrLoopback
6
+ def loopback?
7
+ case @family
8
+ when Socket::AF_INET
9
+ @addr & 0xff000000 == 0x7f000000
10
+ when Socket::AF_INET6
11
+ @addr == 1
12
+ else
13
+ raise AddressFamilyError, "unsupported address family"
14
+ end
15
+ end
16
+ end
17
+
18
+ # For backward compatibility with old rubies
19
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5.0")
20
+ IPAddr.send(:include, Doorkeeper::IPAddrLoopback)
21
+ end
22
+
4
23
  module OAuth
5
24
  module Helpers
6
25
  module URIChecker
@@ -23,10 +42,23 @@ module Doorkeeper
23
42
  client_url.query = nil
24
43
  end
25
44
 
45
+ # RFC8252, Paragraph 7.3
46
+ # @see https://tools.ietf.org/html/rfc8252#section-7.3
47
+ if loopback_uri?(url) && loopback_uri?(client_url)
48
+ url.port = nil
49
+ client_url.port = nil
50
+ end
51
+
26
52
  url.query = nil
27
53
  url == client_url
28
54
  end
29
55
 
56
+ def self.loopback_uri?(uri)
57
+ IPAddr.new(uri.host).loopback?
58
+ rescue IPAddr::Error
59
+ false
60
+ end
61
+
30
62
  def self.valid_for_authorization?(url, client_url)
31
63
  valid?(url) && client_url.split.any? { |other_url| matches?(url, other_url) }
32
64
  end
@@ -32,7 +32,12 @@ module Doorkeeper
32
32
  client_scopes = client.try(:scopes)
33
33
  return true if scopes.blank?
34
34
 
35
- ScopeChecker.valid?(scopes.to_s, server.scopes, client_scopes)
35
+ ScopeChecker.valid?(
36
+ scope_str: scopes.to_s,
37
+ server_scopes: server.scopes,
38
+ app_scopes: client_scopes,
39
+ grant_type: grant_type
40
+ )
36
41
  end
37
42
 
38
43
  def validate_resource_owner
@@ -40,7 +45,7 @@ module Doorkeeper
40
45
  end
41
46
 
42
47
  def validate_client
43
- !parameters[:client_id] || !client.nil?
48
+ !parameters[:client_id] || client.present?
44
49
  end
45
50
  end
46
51
  end
@@ -77,12 +77,17 @@ module Doorkeeper
77
77
  return true if scope.blank?
78
78
 
79
79
  Helpers::ScopeChecker.valid?(
80
- scope,
81
- server.scopes,
82
- client.application.scopes
80
+ scope_str: scope,
81
+ server_scopes: server.scopes,
82
+ app_scopes: client.application.scopes,
83
+ grant_type: grant_type
83
84
  )
84
85
  end
85
86
 
87
+ def grant_type
88
+ response_type == 'code' ? AUTHORIZATION_CODE : IMPLICIT
89
+ end
90
+
86
91
  def validate_redirect_uri
87
92
  return false if redirect_uri.blank?
88
93
 
@@ -99,7 +99,10 @@ module Doorkeeper
99
99
 
100
100
  def validate_scope
101
101
  if @original_scopes.present?
102
- ScopeChecker.valid?(@original_scopes, refresh_token.scopes)
102
+ ScopeChecker.valid?(
103
+ scope_str: @original_scopes,
104
+ server_scopes: refresh_token.scopes
105
+ )
103
106
  else
104
107
  true
105
108
  end
@@ -11,10 +11,10 @@ module Doorkeeper
11
11
 
12
12
  def body
13
13
  {
14
- 'access_token' => token.token,
14
+ 'access_token' => token.plaintext_token,
15
15
  'token_type' => token.token_type,
16
16
  'expires_in' => token.expires_in_seconds,
17
- 'refresh_token' => token.refresh_token,
17
+ 'refresh_token' => token.plaintext_refresh_token,
18
18
  'scope' => token.scopes_string,
19
19
  'created_at' => token.created_at.to_i
20
20
  }.reject { |_, value| value.blank? }
@@ -16,11 +16,30 @@ module Doorkeeper
16
16
 
17
17
  belongs_to :application, belongs_to_options
18
18
 
19
- validates :resource_owner_id, :application_id, :token, :expires_in, :redirect_uri, presence: true
19
+ validates :resource_owner_id,
20
+ :application_id,
21
+ :token,
22
+ :expires_in,
23
+ :redirect_uri,
24
+ presence: true
25
+
20
26
  validates :token, uniqueness: true
21
27
 
22
28
  before_validation :generate_token, on: :create
23
29
 
30
+ # Keep a reference to the generated token during generation
31
+ # of this access grant. The actual token may be mapped by
32
+ # the configuration hasher and may not be available in plaintext.
33
+ #
34
+ # If hash tokens are enabled, this will return nil on fetched tokens
35
+ def plaintext_token
36
+ if perform_secret_hashing?
37
+ @raw_token
38
+ else
39
+ token
40
+ end
41
+ end
42
+
24
43
  private
25
44
 
26
45
  # Generates token value with UniqueToken class.
@@ -28,7 +47,8 @@ module Doorkeeper
28
47
  # @return [String] token value
29
48
  #
30
49
  def generate_token
31
- self.token = UniqueToken.generate
50
+ @raw_token = UniqueToken.generate
51
+ self.token = hashed_or_plain_token(@raw_token)
32
52
  end
33
53
  end
34
54
  end
@@ -45,6 +45,16 @@ module Doorkeeper
45
45
  AccessGrant.revoke_all_for(id, resource_owner)
46
46
  end
47
47
 
48
+ # We keep a volatile copy of the raw client_secret for initial communication
49
+ # The stored secret may be mapped and not available in cleartext.
50
+ def plaintext_secret
51
+ if perform_secret_hashing?
52
+ @raw_secret
53
+ else
54
+ secret
55
+ end
56
+ end
57
+
48
58
  private
49
59
 
50
60
  def generate_uid
@@ -52,12 +62,16 @@ module Doorkeeper
52
62
  end
53
63
 
54
64
  def generate_secret
55
- self.secret = UniqueToken.generate if secret.blank?
65
+ return unless secret.blank?
66
+
67
+ @raw_secret = UniqueToken.generate
68
+ self.secret = hashed_or_plain_token(@raw_secret)
56
69
  end
57
70
 
58
71
  def scopes_match_configured
59
72
  if scopes.present? &&
60
- !ScopeChecker.valid?(scopes.to_s, Doorkeeper.configuration.scopes)
73
+ !ScopeChecker.valid?(scope_str: scopes.to_s,
74
+ server_scopes: Doorkeeper.configuration.scopes)
61
75
  errors.add(:scopes, :not_match_configured)
62
76
  end
63
77
  end
@@ -8,9 +8,9 @@ module Doorkeeper
8
8
  module VERSION
9
9
  # Semantic versioning
10
10
  MAJOR = 5
11
- MINOR = 0
12
- TINY = 2
13
- PRE = nil
11
+ MINOR = 1
12
+ TINY = 0
13
+ PRE = 'rc1'
14
14
 
15
15
  # Full version number
16
16
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
data/lib/doorkeeper.rb CHANGED
@@ -56,6 +56,7 @@ require 'doorkeeper/models/concerns/scopes'
56
56
  require 'doorkeeper/models/concerns/expirable'
57
57
  require 'doorkeeper/models/concerns/revocable'
58
58
  require 'doorkeeper/models/concerns/accessible'
59
+ require 'doorkeeper/models/concerns/hashable'
59
60
 
60
61
  require 'doorkeeper/models/access_grant_mixin'
61
62
  require 'doorkeeper/models/access_token_mixin'
@@ -75,8 +75,39 @@ Doorkeeper.configure do
75
75
  # doesn't updates existing token expiration time, it will create a new token instead.
76
76
  # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
77
77
  #
78
+ # You can not enable this option together with +hash_token_secrets+.
79
+ #
78
80
  # reuse_access_token
79
81
 
82
+ # Hash access and refresh tokens before persisting them.
83
+ # Note: This will disable the possibility to use +reuse_access_token+
84
+ # since plain values can no longer be retrieved.
85
+ #
86
+ # hash_token_secrets
87
+
88
+ # Hash application secrets before persisting them.
89
+ #
90
+ # hash_application_secrets
91
+
92
+ # When the above option is enabled,
93
+ # and a hashed token or secret is not found,
94
+ # look up the plain text token as a fallback.
95
+ #
96
+ # This will ensure that old access tokens and secrets
97
+ # will remain valid even if the hashing above is enabled
98
+ #
99
+ # fallback_to_plain_secrets
100
+
101
+ #
102
+ # Since old values will not be re-hashed, lookups to tokens and secrets
103
+ # will fall back to plain value comparison so any existing tokens will
104
+ # not be invalidated.
105
+ #
106
+ # For example, to use SHA256 digests on plain values, uncomment these lines:
107
+ # hash_secrets do |plain_value|
108
+ # Digest::SHA256.hexdigest plain_value
109
+ # end
110
+
80
111
  # Issue access tokens with refresh token (disabled by default), you may also
81
112
  # pass a block which accepts `context` to customize when to give a refresh
82
113
  # token or not. Similar to `custom_access_token_expires_in`, `context` has
@@ -108,6 +139,15 @@ Doorkeeper.configure do
108
139
  # default_scopes :public
109
140
  # optional_scopes :write, :update
110
141
 
142
+ # Define scopes_by_grant_type to restrict only certain scopes for grant_type
143
+ # By default, all the scopes will be available for all the grant types.
144
+ #
145
+ # Keys to this hash should be the name of grant_type and
146
+ # values should be the array of scopes for that grant type.
147
+ # Note: scopes should be from configured_scopes(i.e. deafult or optional)
148
+ #
149
+ # scopes_by_grant_type password: [:write], client_credentials: [:update]
150
+
111
151
  # Change the way client credentials are retrieved from the request object.
112
152
  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
113
153
  # falls back to the `:client_id` and `:client_secret` params from the `params` object.
@@ -195,7 +235,7 @@ Doorkeeper.configure do
195
235
  # end
196
236
 
197
237
  # Hook into Authorization flow in order to implement Single Sign Out
198
- # or add ny other functionality.
238
+ # or add any other functionality.
199
239
  #
200
240
  # before_successful_authorization do |controller|
201
241
  # Rails.logger.info(params.inspect)
@@ -7,6 +7,10 @@ describe Doorkeeper::ApplicationMetalController do
7
7
  def index
8
8
  render json: {}, status: 200
9
9
  end
10
+
11
+ def create
12
+ render json: {}, status: 200
13
+ end
10
14
  end
11
15
 
12
16
  it "lazy run hooks" do
@@ -22,13 +26,18 @@ describe Doorkeeper::ApplicationMetalController do
22
26
  context 'enabled' do
23
27
  let(:flag) { true }
24
28
 
25
- it '200 for the correct media type' do
26
- get :index, params: {}, as: :url_encoded_form
29
+ it 'returns a 200 for the requests without body' do
30
+ get :index, params: {}
27
31
  expect(response).to have_http_status 200
28
32
  end
29
33
 
30
- it 'returns a 415 for an incorrect media type' do
31
- get :index, as: :json
34
+ it 'returns a 200 for the requests with body and correct media type' do
35
+ post :create, params: {}, as: :url_encoded_form
36
+ expect(response).to have_http_status 200
37
+ end
38
+
39
+ it 'returns a 415 for the requests with body and incorrect media type' do
40
+ post :create, params: {}, as: :json
32
41
  expect(response).to have_http_status 415
33
42
  end
34
43
  end
@@ -45,6 +54,11 @@ describe Doorkeeper::ApplicationMetalController do
45
54
  get :index, as: :json
46
55
  expect(response).to have_http_status 200
47
56
  end
57
+
58
+ it 'returns a 200 for the requests with body and incorrect media type' do
59
+ post :create, params: {}, as: :json
60
+ expect(response).to have_http_status 200
61
+ end
48
62
  end
49
63
  end
50
64
  end
@@ -28,7 +28,7 @@ describe Doorkeeper::TokensController do
28
28
  describe 'when there is a failure due to a custom error' do
29
29
  it 'returns the error response with a custom message' do
30
30
  # I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
31
- custom_message = "my_message"
31
+ custom_message = 'my_message'
32
32
  allow(I18n).to receive(:translate)
33
33
  .with(
34
34
  custom_message,
@@ -60,21 +60,17 @@ describe Doorkeeper::TokensController do
60
60
  let(:client) { FactoryBot.create(:application) }
61
61
  let(:access_token) { FactoryBot.create(:access_token, application: client) }
62
62
 
63
- before(:each) do
64
- allow(controller).to receive(:token) { access_token }
65
- end
66
-
67
63
  context 'when associated app is public' do
68
64
  let(:client) { FactoryBot.create(:application, confidential: false) }
69
65
 
70
66
  it 'returns 200' do
71
- post :revoke
67
+ post :revoke, params: { token: access_token.token }
72
68
 
73
69
  expect(response.status).to eq 200
74
70
  end
75
71
 
76
72
  it 'revokes the access token' do
77
- post :revoke
73
+ post :revoke, params: { token: access_token.token }
78
74
 
79
75
  expect(access_token.reload).to have_attributes(revoked?: true)
80
76
  end
@@ -89,13 +85,13 @@ describe Doorkeeper::TokensController do
89
85
  end
90
86
 
91
87
  it 'returns 200' do
92
- post :revoke
88
+ post :revoke, params: { token: access_token.token }
93
89
 
94
90
  expect(response.status).to eq 200
95
91
  end
96
92
 
97
93
  it 'revokes the access token' do
98
- post :revoke
94
+ post :revoke, params: { token: access_token.token }
99
95
 
100
96
  expect(access_token.reload).to have_attributes(revoked?: true)
101
97
  end
@@ -105,13 +101,13 @@ describe Doorkeeper::TokensController do
105
101
  let(:oauth_client) { Doorkeeper::OAuth::Client.new(some_other_client) }
106
102
 
107
103
  it 'returns 200' do
108
- post :revoke
104
+ post :revoke, params: { token: access_token.token }
109
105
 
110
106
  expect(response.status).to eq 200
111
107
  end
112
108
 
113
109
  it 'does not revoke the access token' do
114
- post :revoke
110
+ post :revoke, params: { token: access_token.token }
115
111
 
116
112
  expect(access_token.reload).to have_attributes(revoked?: false)
117
113
  end
@@ -1,3 +1,3 @@
1
1
  class ApplicationController < ActionController::Base
2
- protect_from_forgery
2
+ protect_from_forgery with: :exception
3
3
  end