doorkeeper 5.0.2 → 5.1.0.rc2

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 (94) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +17 -4
  3. data/Appraisals +29 -3
  4. data/Dangerfile +5 -2
  5. data/Gemfile +14 -4
  6. data/NEWS.md +64 -19
  7. data/README.md +68 -487
  8. data/app/controllers/doorkeeper/token_info_controller.rb +1 -1
  9. data/app/controllers/doorkeeper/tokens_controller.rb +7 -7
  10. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  11. data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
  12. data/bin/console +15 -0
  13. data/doorkeeper.gemspec +3 -2
  14. data/gemfiles/rails_4_2.gemfile +8 -4
  15. data/gemfiles/rails_5_0.gemfile +9 -5
  16. data/gemfiles/rails_5_1.gemfile +9 -5
  17. data/gemfiles/rails_5_2.gemfile +9 -5
  18. data/gemfiles/rails_6_0.gemfile +16 -0
  19. data/gemfiles/rails_master.gemfile +8 -9
  20. data/lib/doorkeeper/config.rb +164 -11
  21. data/lib/doorkeeper/helpers/controller.rb +3 -2
  22. data/lib/doorkeeper/models/access_grant_mixin.rb +16 -1
  23. data/lib/doorkeeper/models/access_token_mixin.rb +54 -10
  24. data/lib/doorkeeper/models/application_mixin.rb +42 -1
  25. data/lib/doorkeeper/models/concerns/expirable.rb +3 -2
  26. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  27. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  28. data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
  29. data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
  30. data/lib/doorkeeper/oauth/authorization/token.rb +4 -2
  31. data/lib/doorkeeper/oauth/authorization_code_request.rb +1 -1
  32. data/lib/doorkeeper/oauth/client.rb +1 -1
  33. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -3
  34. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  35. data/lib/doorkeeper/oauth/error_response.rb +5 -1
  36. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
  37. data/lib/doorkeeper/oauth/helpers/unique_token.rb +12 -1
  38. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +32 -0
  39. data/lib/doorkeeper/oauth/invalid_token_response.rb +4 -0
  40. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  41. data/lib/doorkeeper/oauth/pre_authorization.rb +8 -3
  42. data/lib/doorkeeper/oauth/refresh_token_request.rb +4 -1
  43. data/lib/doorkeeper/oauth/token_introspection.rb +72 -6
  44. data/lib/doorkeeper/oauth/token_response.rb +2 -2
  45. data/lib/doorkeeper/orm/active_record/access_grant.rb +23 -2
  46. data/lib/doorkeeper/orm/active_record/application.rb +20 -2
  47. data/lib/doorkeeper/secret_storing/base.rb +63 -0
  48. data/lib/doorkeeper/secret_storing/bcrypt.rb +59 -0
  49. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  50. data/lib/doorkeeper/secret_storing/sha256_hash.rb +25 -0
  51. data/lib/doorkeeper/version.rb +3 -3
  52. data/lib/doorkeeper.rb +7 -0
  53. data/lib/generators/doorkeeper/templates/initializer.rb +90 -8
  54. data/spec/controllers/application_metal_controller_spec.rb +18 -4
  55. data/spec/controllers/authorizations_controller_spec.rb +3 -3
  56. data/spec/controllers/token_info_controller_spec.rb +1 -1
  57. data/spec/controllers/tokens_controller_spec.rb +85 -41
  58. data/spec/dummy/app/controllers/application_controller.rb +1 -1
  59. data/spec/dummy/config/application.rb +12 -1
  60. data/spec/factories.rb +3 -3
  61. data/spec/lib/config_spec.rb +168 -0
  62. data/spec/lib/models/expirable_spec.rb +12 -0
  63. data/spec/lib/models/reusable_spec.rb +40 -0
  64. data/spec/lib/models/scopes_spec.rb +13 -1
  65. data/spec/lib/models/secret_storable_spec.rb +113 -0
  66. data/spec/lib/oauth/authorization_code_request_spec.rb +18 -1
  67. data/spec/lib/oauth/base_request_spec.rb +7 -7
  68. data/spec/lib/oauth/client_credentials/creator_spec.rb +51 -7
  69. data/spec/lib/oauth/client_credentials/validation_spec.rb +3 -0
  70. data/spec/lib/oauth/error_response_spec.rb +7 -1
  71. data/spec/lib/oauth/helpers/scope_checker_spec.rb +52 -17
  72. data/spec/lib/oauth/helpers/uri_checker_spec.rb +20 -2
  73. data/spec/lib/oauth/password_access_token_request_spec.rb +43 -12
  74. data/spec/lib/oauth/pre_authorization_spec.rb +24 -0
  75. data/spec/lib/oauth/token_request_spec.rb +16 -1
  76. data/spec/lib/oauth/token_response_spec.rb +13 -13
  77. data/spec/lib/oauth/token_spec.rb +14 -0
  78. data/spec/lib/secret_storing/base_spec.rb +60 -0
  79. data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
  80. data/spec/lib/secret_storing/plain_spec.rb +44 -0
  81. data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
  82. data/spec/models/doorkeeper/access_grant_spec.rb +61 -0
  83. data/spec/models/doorkeeper/access_token_spec.rb +123 -0
  84. data/spec/models/doorkeeper/application_spec.rb +56 -0
  85. data/spec/requests/flows/authorization_code_spec.rb +41 -1
  86. data/spec/requests/flows/client_credentials_spec.rb +2 -2
  87. data/spec/requests/flows/implicit_grant_spec.rb +1 -1
  88. data/spec/requests/flows/password_spec.rb +7 -5
  89. data/spec/requests/flows/revoke_token_spec.rb +14 -30
  90. data/spec/routing/custom_controller_routes_spec.rb +4 -0
  91. data/spec/spec_helper.rb +2 -1
  92. data/spec/support/ruby_2_6_rails_4_2_patch.rb +14 -0
  93. data/spec/support/shared/hashing_shared_context.rb +36 -0
  94. metadata +59 -22
@@ -16,11 +16,31 @@ 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
+ # We keep a volatile copy of the raw token for initial communication
31
+ # The stored refresh_token may be mapped and not available in cleartext.
32
+ #
33
+ # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
34
+ # while hashing strategies do not, so you cannot rely on this value
35
+ # returning a present value for persisted tokens.
36
+ def plaintext_token
37
+ if secret_strategy.allows_restoring_secrets?
38
+ secret_strategy.restore_secret(self, :token)
39
+ else
40
+ @raw_token
41
+ end
42
+ end
43
+
24
44
  private
25
45
 
26
46
  # Generates token value with UniqueToken class.
@@ -28,7 +48,8 @@ module Doorkeeper
28
48
  # @return [String] token value
29
49
  #
30
50
  def generate_token
31
- self.token = UniqueToken.generate
51
+ @raw_token = UniqueToken.generate
52
+ secret_strategy.store_secret(self, :token, @raw_token)
32
53
  end
33
54
  end
34
55
  end
@@ -45,6 +45,20 @@ 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 secret for initial communication
49
+ # The stored refresh_token may be mapped and not available in cleartext.
50
+ #
51
+ # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
52
+ # while hashing strategies do not, so you cannot rely on this value
53
+ # returning a present value for persisted tokens.
54
+ def plaintext_secret
55
+ if secret_strategy.allows_restoring_secrets?
56
+ secret_strategy.restore_secret(self, :secret)
57
+ else
58
+ @raw_secret
59
+ end
60
+ end
61
+
48
62
  private
49
63
 
50
64
  def generate_uid
@@ -52,12 +66,16 @@ module Doorkeeper
52
66
  end
53
67
 
54
68
  def generate_secret
55
- self.secret = UniqueToken.generate if secret.blank?
69
+ return unless secret.blank?
70
+
71
+ @raw_secret = UniqueToken.generate
72
+ secret_strategy.store_secret(self, :secret, @raw_secret)
56
73
  end
57
74
 
58
75
  def scopes_match_configured
59
76
  if scopes.present? &&
60
- !ScopeChecker.valid?(scopes.to_s, Doorkeeper.configuration.scopes)
77
+ !ScopeChecker.valid?(scope_str: scopes.to_s,
78
+ server_scopes: Doorkeeper.configuration.scopes)
61
79
  errors.add(:scopes, :not_match_configured)
62
80
  end
63
81
  end
@@ -0,0 +1,63 @@
1
+ module Doorkeeper
2
+ module SecretStoring
3
+
4
+ ##
5
+ # Base class for secret storing, including common helpers
6
+ class Base
7
+ ##
8
+ # Return the value to be stored by the database
9
+ # used for looking up a database value.
10
+ # @param plain_secret The plain secret input / generated
11
+ def self.transform_secret(plain_secret)
12
+ raise NotImplementedError
13
+ end
14
+
15
+ ##
16
+ # Transform and store the given secret attribute => value
17
+ # pair used for safely storing the attribute
18
+ # @param resource The model instance being modified
19
+ # @param attribute The secret attribute
20
+ # @param plain_secret The plain secret input / generated
21
+ def self.store_secret(resource, attribute, plain_secret)
22
+ transformed_value = self.transform_secret plain_secret
23
+ resource.public_send :"#{attribute}=", transformed_value
24
+
25
+ transformed_value
26
+ end
27
+
28
+ ##
29
+ # Return the restored value from the database
30
+ # @param resource The resource instance to act on
31
+ # @param attribute The secret attribute to restore
32
+ # as retrieved from the database.
33
+ def self.restore_secret(resource, attribute)
34
+ raise NotImplementedError
35
+ end
36
+
37
+ ##
38
+ # Determines whether this strategy supports restoring
39
+ # secrets from the database. This allows detecting users
40
+ # trying to use a non-restorable strategy with +reuse_access_tokens+.
41
+ def self.allows_restoring_secrets?
42
+ false
43
+ end
44
+
45
+ ##
46
+ # Determines what secrets this strategy is applicable for
47
+ def self.validate_for(model)
48
+ valid = %i[token application]
49
+ return true if valid.include?(model.to_sym)
50
+
51
+ raise ArgumentError, "'#{name}' can not be used for #{model}."
52
+ end
53
+
54
+ ##
55
+ # Securely compare the given +input+ value with a +stored+ value
56
+ # processed by +transform_secret+.
57
+ def self.secret_matches?(input, stored)
58
+ transformed_input = transform_secret(input)
59
+ ActiveSupport::SecurityUtils.secure_compare transformed_input, stored
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,59 @@
1
+ module Doorkeeper
2
+ module SecretStoring
3
+
4
+ ##
5
+ # Plain text secret storing, which is the default
6
+ # but also provides fallback lookup if
7
+ # other secret storing mechanisms are enabled.
8
+ class BCrypt < Base
9
+ ##
10
+ # Return the value to be stored by the database
11
+ # @param plain_secret The plain secret input / generated
12
+ def self.transform_secret(plain_secret)
13
+ ::BCrypt::Password.create(plain_secret.to_s)
14
+ end
15
+
16
+ ##
17
+ # Securely compare the given +input+ value with a +stored+ value
18
+ # processed by +transform_secret+.
19
+ def self.secret_matches?(input, stored)
20
+ ::BCrypt::Password.new(stored.to_s) == input.to_s
21
+ rescue ::BCrypt::Errors::InvalidHash
22
+ false
23
+ end
24
+
25
+ ##
26
+ # Determines whether this strategy supports restoring
27
+ # secrets from the database. This allows detecting users
28
+ # trying to use a non-restorable strategy with +reuse_access_tokens+.
29
+ def self.allows_restoring_secrets?
30
+ false
31
+ end
32
+
33
+ ##
34
+ # Determines what secrets this strategy is applicable for
35
+ def self.validate_for(model)
36
+ unless model.to_sym == :application
37
+ raise ArgumentError,
38
+ "'#{name}' can only be used for storing application secrets."
39
+ end
40
+
41
+ unless bcrypt_present?
42
+ raise ArgumentError,
43
+ "'#{name}' requires the 'bcrypt' gem being loaded."
44
+ end
45
+
46
+ true
47
+ end
48
+
49
+ ##
50
+ # Test if we can require the BCrypt gem
51
+ def self.bcrypt_present?
52
+ require 'bcrypt'
53
+ true
54
+ rescue LoadError
55
+ false
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,33 @@
1
+ module Doorkeeper
2
+ module SecretStoring
3
+
4
+ ##
5
+ # Plain text secret storing, which is the default
6
+ # but also provides fallback lookup if
7
+ # other secret storing mechanisms are enabled.
8
+ class Plain < Base
9
+
10
+ ##
11
+ # Return the value to be stored by the database
12
+ # @param plain_secret The plain secret input / generated
13
+ def self.transform_secret(plain_secret)
14
+ plain_secret
15
+ end
16
+
17
+ ##
18
+ # Return the restored value from the database
19
+ # @param resource The resource instance to act on
20
+ # @param attribute The secret attribute to restore
21
+ # as retrieved from the database.
22
+ def self.restore_secret(resource, attribute)
23
+ resource.public_send attribute
24
+ end
25
+
26
+ ##
27
+ # Plain values obviously allow restoring
28
+ def self.allows_restoring_secrets?
29
+ true
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ module Doorkeeper
2
+ module SecretStoring
3
+
4
+ ##
5
+ # Plain text secret storing, which is the default
6
+ # but also provides fallback lookup if
7
+ # other secret storing mechanisms are enabled.
8
+ class Sha256Hash < Base
9
+ ##
10
+ # Return the value to be stored by the database
11
+ # @param plain_secret The plain secret input / generated
12
+ def self.transform_secret(plain_secret)
13
+ ::Digest::SHA256.hexdigest plain_secret
14
+ end
15
+
16
+ ##
17
+ # Determines whether this strategy supports restoring
18
+ # secrets from the database. This allows detecting users
19
+ # trying to use a non-restorable strategy with +reuse_access_tokens+.
20
+ def self.allows_restoring_secrets?
21
+ false
22
+ end
23
+ end
24
+ end
25
+ 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 = 'rc2'
14
14
 
15
15
  # Full version number
16
16
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
data/lib/doorkeeper.rb CHANGED
@@ -51,11 +51,18 @@ require 'doorkeeper/oauth/token_introspection'
51
51
  require 'doorkeeper/oauth/invalid_token_response'
52
52
  require 'doorkeeper/oauth/forbidden_token_response'
53
53
 
54
+ require 'doorkeeper/secret_storing/base'
55
+ require 'doorkeeper/secret_storing/plain'
56
+ require 'doorkeeper/secret_storing/sha256_hash'
57
+ require 'doorkeeper/secret_storing/bcrypt'
58
+
54
59
  require 'doorkeeper/models/concerns/orderable'
55
60
  require 'doorkeeper/models/concerns/scopes'
56
61
  require 'doorkeeper/models/concerns/expirable'
62
+ require 'doorkeeper/models/concerns/reusable'
57
63
  require 'doorkeeper/models/concerns/revocable'
58
64
  require 'doorkeeper/models/concerns/accessible'
65
+ require 'doorkeeper/models/concerns/secret_storable'
59
66
 
60
67
  require 'doorkeeper/models/access_grant_mixin'
61
68
  require 'doorkeeper/models/access_token_mixin'
@@ -64,7 +64,7 @@ Doorkeeper.configure do
64
64
 
65
65
  # The controller Doorkeeper::ApplicationController inherits from.
66
66
  # Defaults to ActionController::Base.
67
- # See https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
67
+ # See https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
68
68
  #
69
69
  # base_controller 'ApplicationController'
70
70
 
@@ -75,8 +75,63 @@ 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
+ # Set a limit for token_reuse if using reuse_access_token option
83
+ #
84
+ # This option limits token_reusability to some extent.
85
+ # If not set then access_token will be reused unless it expires.
86
+ # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
87
+ #
88
+ # This option should be a percentage(i.e. (0,100])
89
+ #
90
+ # token_reuse_limit 100
91
+
92
+ # Hash access and refresh tokens before persisting them.
93
+ # This will disable the possibility to use +reuse_access_token+
94
+ # since plain values can no longer be retrieved.
95
+ #
96
+ # Note: If you are already a user of doorkeeper and have existing tokens
97
+ # in your installation, they will be invalid without enabling the additional
98
+ # setting `fallback_to_plain_secrets` below.
99
+ #
100
+ # hash_token_secrets
101
+ # By default, token secrets will be hashed using the
102
+ # +Doorkeeper::Hashing::SHA256+ strategy.
103
+ #
104
+ # If you wish to use another hashing implementation, you can override
105
+ # this strategy as follows:
106
+ #
107
+ # hash_token_secrets using: '::Doorkeeper::Hashing::MyCustomHashImpl'
108
+ #
109
+ # Keep in mind that changing the hashing function will invalidate all existing
110
+ # secrets, if there are any.
111
+
112
+ # Hash application secrets before persisting them.
113
+ #
114
+ # hash_application_secrets
115
+ #
116
+ # By default, applications will be hashed
117
+ # with the +Doorkeeper::SecretStoring::SHA256+ strategy.
118
+ #
119
+ # If you wish to use bcrypt for application secret hashing, uncomment
120
+ # this line instead:
121
+ #
122
+ # hash_application_secrets using: '::Doorkeeper::SecretStoring::BCrypt'
123
+
124
+ # When the above option is enabled,
125
+ # and a hashed token or secret is not found,
126
+ # you can allow to fall back to another strategy.
127
+ # For users upgrading doorkeeper and wishing to enable hashing,
128
+ # you will probably want to enable the fallback to plain tokens.
129
+ #
130
+ # This will ensure that old access tokens and secrets
131
+ # will remain valid even if the hashing above is enabled.
132
+ #
133
+ # fallback_to_plain_secrets
134
+
80
135
  # Issue access tokens with refresh token (disabled by default), you may also
81
136
  # pass a block which accepts `context` to customize when to give a refresh
82
137
  # token or not. Similar to `custom_access_token_expires_in`, `context` has
@@ -88,12 +143,6 @@ Doorkeeper.configure do
88
143
  #
89
144
  # use_refresh_token
90
145
 
91
- # Forbids creating/updating applications with arbitrary scopes that are
92
- # not in configuration, i.e. `default_scopes` or `optional_scopes`.
93
- # (disabled by default)
94
- #
95
- # enforce_configured_scopes
96
-
97
146
  # Provide support for an owner to be assigned to each registered application (disabled by default)
98
147
  # Optional parameter confirmation: true (default false) if you want to enforce ownership of
99
148
  # a registered application
@@ -108,6 +157,21 @@ Doorkeeper.configure do
108
157
  # default_scopes :public
109
158
  # optional_scopes :write, :update
110
159
 
160
+ # Define scopes_by_grant_type to restrict only certain scopes for grant_type
161
+ # By default, all the scopes will be available for all the grant types.
162
+ #
163
+ # Keys to this hash should be the name of grant_type and
164
+ # values should be the array of scopes for that grant type.
165
+ # Note: scopes should be from configured_scopes(i.e. deafult or optional)
166
+ #
167
+ # scopes_by_grant_type password: [:write], client_credentials: [:update]
168
+
169
+ # Forbids creating/updating applications with arbitrary scopes that are
170
+ # not in configuration, i.e. `default_scopes` or `optional_scopes`.
171
+ # (disabled by default)
172
+ #
173
+ # enforce_configured_scopes
174
+
111
175
  # Change the way client credentials are retrieved from the request object.
112
176
  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
113
177
  # falls back to the `:client_id` and `:client_secret` params from the `params` object.
@@ -165,6 +229,24 @@ Doorkeeper.configure do
165
229
  #
166
230
  # handle_auth_errors :raise
167
231
 
232
+ # Customize token introspection response.
233
+ # Allows to add your own fields to default one that are required by the OAuth spec
234
+ # for the introspection response. It could be `sub`, `aud` and so on.
235
+ # This configuration option can be a proc, lambda or any Ruby object responds
236
+ # to `.call` method and result of it's invocation must be a Hash.
237
+ #
238
+ # custom_introspection_response do |token, context|
239
+ # {
240
+ # "sub": "Z5O3upPC88QrAjx00dis",
241
+ # "aud": "https://protected.example.net/resource",
242
+ # "username": User.find(token.resource_owner_id).username
243
+ # }
244
+ # end
245
+ #
246
+ # or
247
+ #
248
+ # custom_introspection_response CustomIntrospectionResponder
249
+
168
250
  # Specify what grant flows are enabled in array of Strings. The valid
169
251
  # strings and the flows they enable are:
170
252
  #
@@ -195,7 +277,7 @@ Doorkeeper.configure do
195
277
  # end
196
278
 
197
279
  # Hook into Authorization flow in order to implement Single Sign Out
198
- # or add ny other functionality.
280
+ # or add any other functionality.
199
281
  #
200
282
  # before_successful_authorization do |controller|
201
283
  # 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
@@ -91,7 +91,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
91
91
  end
92
92
 
93
93
  it "includes access token in fragment" do
94
- expect(redirect_uri.match(/access_token=([a-f0-9]+)&?/)[1]).to eq(Doorkeeper::AccessToken.first.token)
94
+ expect(redirect_uri.match(/access_token=([a-zA-Z0-9\-_]+)&?/)[1]).to eq(Doorkeeper::AccessToken.first.token)
95
95
  end
96
96
 
97
97
  it "includes token type in fragment" do
@@ -165,7 +165,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
165
165
  let(:redirect_uri) { response_json_body['redirect_uri'] }
166
166
 
167
167
  it 'renders 400 error' do
168
- expect(response.status).to eq 401
168
+ expect(response.status).to eq 400
169
169
  end
170
170
 
171
171
  it 'includes correct redirect URI' do
@@ -408,7 +408,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
408
408
  expect(redirect_uri.match(/token_type=(\w+)&?/)[1]).to eq "Bearer"
409
409
  expect(redirect_uri.match(/expires_in=(\d+)&?/)[1].to_i).to eq 1234
410
410
  expect(
411
- redirect_uri.match(/access_token=([a-f0-9]+)&?/)[1]
411
+ redirect_uri.match(/access_token=([a-zA-Z0-9\-_]+)&?/)[1]
412
412
  ).to eq Doorkeeper::AccessToken.first.token
413
413
  end
414
414
 
@@ -40,7 +40,7 @@ describe Doorkeeper::TokenInfoController do
40
40
  get :show
41
41
 
42
42
  expect(response.body).to eq(
43
- Doorkeeper::OAuth::ErrorResponse.new(name: :invalid_request, status: :unauthorized).body.to_json
43
+ Doorkeeper::OAuth::InvalidTokenResponse.new.body.to_json
44
44
  )
45
45
  end
46
46
  end