doorkeeper 5.0.0 → 5.0.1

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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -0
  3. data/Dangerfile +57 -0
  4. data/NEWS.md +32 -1
  5. data/README.md +18 -3
  6. data/app/controllers/doorkeeper/application_controller.rb +2 -0
  7. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -0
  8. data/app/controllers/doorkeeper/applications_controller.rb +4 -2
  9. data/app/controllers/doorkeeper/authorizations_controller.rb +3 -3
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -0
  11. data/app/controllers/doorkeeper/token_info_controller.rb +2 -0
  12. data/app/controllers/doorkeeper/tokens_controller.rb +2 -0
  13. data/app/helpers/doorkeeper/dashboard_helper.rb +2 -0
  14. data/app/validators/redirect_uri_validator.rb +2 -0
  15. data/doorkeeper.gemspec +23 -22
  16. data/lib/doorkeeper.rb +1 -0
  17. data/lib/doorkeeper/config.rb +7 -2
  18. data/lib/doorkeeper/engine.rb +2 -0
  19. data/lib/doorkeeper/errors.rb +17 -0
  20. data/lib/doorkeeper/grape/authorization_decorator.rb +2 -0
  21. data/lib/doorkeeper/grape/helpers.rb +2 -0
  22. data/lib/doorkeeper/helpers/controller.rb +2 -0
  23. data/lib/doorkeeper/models/access_grant_mixin.rb +5 -3
  24. data/lib/doorkeeper/models/access_token_mixin.rb +5 -3
  25. data/lib/doorkeeper/models/application_mixin.rb +2 -0
  26. data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
  27. data/lib/doorkeeper/models/concerns/expirable.rb +2 -0
  28. data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
  29. data/lib/doorkeeper/models/concerns/ownership.rb +2 -0
  30. data/lib/doorkeeper/models/concerns/revocable.rb +2 -0
  31. data/lib/doorkeeper/models/concerns/scopes.rb +2 -0
  32. data/lib/doorkeeper/oauth/authorization/code.rb +2 -0
  33. data/lib/doorkeeper/oauth/authorization/context.rb +2 -0
  34. data/lib/doorkeeper/oauth/authorization/token.rb +2 -0
  35. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
  36. data/lib/doorkeeper/oauth/authorization_code_request.rb +2 -0
  37. data/lib/doorkeeper/oauth/base_request.rb +2 -0
  38. data/lib/doorkeeper/oauth/base_response.rb +2 -0
  39. data/lib/doorkeeper/oauth/client.rb +2 -0
  40. data/lib/doorkeeper/oauth/client/credentials.rb +2 -0
  41. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -0
  42. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +2 -0
  43. data/lib/doorkeeper/oauth/client_credentials/validation.rb +2 -0
  44. data/lib/doorkeeper/oauth/client_credentials_request.rb +2 -0
  45. data/lib/doorkeeper/oauth/code_request.rb +2 -0
  46. data/lib/doorkeeper/oauth/code_response.rb +2 -0
  47. data/lib/doorkeeper/oauth/error.rb +2 -0
  48. data/lib/doorkeeper/oauth/error_response.rb +10 -0
  49. data/lib/doorkeeper/oauth/forbidden_token_response.rb +9 -2
  50. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -0
  51. data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -0
  52. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +5 -2
  53. data/lib/doorkeeper/oauth/invalid_token_response.rb +18 -0
  54. data/lib/doorkeeper/oauth/password_access_token_request.rb +2 -0
  55. data/lib/doorkeeper/oauth/pre_authorization.rb +2 -0
  56. data/lib/doorkeeper/oauth/refresh_token_request.rb +10 -2
  57. data/lib/doorkeeper/oauth/scopes.rb +2 -0
  58. data/lib/doorkeeper/oauth/token.rb +2 -0
  59. data/lib/doorkeeper/oauth/token_introspection.rb +2 -0
  60. data/lib/doorkeeper/oauth/token_request.rb +2 -0
  61. data/lib/doorkeeper/oauth/token_response.rb +2 -0
  62. data/lib/doorkeeper/orm/active_record.rb +2 -0
  63. data/lib/doorkeeper/rails/helpers.rb +4 -0
  64. data/lib/doorkeeper/rails/routes.rb +9 -2
  65. data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
  66. data/lib/doorkeeper/rails/routes/mapping.rb +2 -0
  67. data/lib/doorkeeper/rake/db.rake +4 -4
  68. data/lib/doorkeeper/request.rb +2 -0
  69. data/lib/doorkeeper/request/authorization_code.rb +2 -0
  70. data/lib/doorkeeper/request/client_credentials.rb +2 -0
  71. data/lib/doorkeeper/request/code.rb +2 -0
  72. data/lib/doorkeeper/request/password.rb +2 -0
  73. data/lib/doorkeeper/request/refresh_token.rb +2 -0
  74. data/lib/doorkeeper/request/strategy.rb +2 -0
  75. data/lib/doorkeeper/request/token.rb +2 -0
  76. data/lib/doorkeeper/server.rb +2 -0
  77. data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
  78. data/lib/doorkeeper/validations.rb +2 -0
  79. data/lib/doorkeeper/version.rb +3 -1
  80. data/lib/generators/doorkeeper/templates/initializer.rb +20 -2
  81. data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -2
  82. data/spec/controllers/applications_controller_spec.rb +37 -41
  83. data/spec/controllers/authorizations_controller_spec.rb +71 -18
  84. data/spec/controllers/protected_resources_controller_spec.rb +44 -2
  85. data/spec/controllers/tokens_controller_spec.rb +4 -5
  86. data/spec/dummy/Rakefile +1 -1
  87. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +1 -1
  88. data/spec/dummy/app/controllers/home_controller.rb +1 -2
  89. data/spec/dummy/config.ru +1 -1
  90. data/spec/dummy/config/application.rb +1 -1
  91. data/spec/dummy/config/boot.rb +2 -4
  92. data/spec/dummy/config/environment.rb +1 -1
  93. data/spec/dummy/config/environments/test.rb +1 -1
  94. data/spec/dummy/config/initializers/doorkeeper.rb +2 -1
  95. data/spec/dummy/config/initializers/new_framework_defaults.rb +1 -3
  96. data/spec/dummy/config/initializers/secret_token.rb +1 -1
  97. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +4 -4
  98. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
  99. data/spec/dummy/script/rails +4 -3
  100. data/spec/factories.rb +6 -6
  101. data/spec/generators/install_generator_spec.rb +4 -1
  102. data/spec/generators/templates/routes.rb +0 -1
  103. data/spec/generators/views_generator_spec.rb +1 -1
  104. data/spec/grape/grape_integration_spec.rb +1 -1
  105. data/spec/lib/config_spec.rb +25 -8
  106. data/spec/lib/doorkeeper_spec.rb +5 -5
  107. data/spec/lib/oauth/authorization_code_request_spec.rb +9 -6
  108. data/spec/lib/oauth/base_request_spec.rb +10 -10
  109. data/spec/lib/oauth/client/credentials_spec.rb +2 -2
  110. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -2
  111. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -1
  112. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  113. data/spec/lib/oauth/code_request_spec.rb +2 -2
  114. data/spec/lib/oauth/code_response_spec.rb +1 -1
  115. data/spec/lib/oauth/helpers/scope_checker_spec.rb +8 -8
  116. data/spec/lib/oauth/helpers/uri_checker_spec.rb +17 -6
  117. data/spec/lib/oauth/password_access_token_request_spec.rb +17 -5
  118. data/spec/lib/oauth/refresh_token_request_spec.rb +11 -7
  119. data/spec/lib/oauth/token_request_spec.rb +5 -5
  120. data/spec/lib/oauth/token_spec.rb +4 -1
  121. data/spec/lib/server_spec.rb +6 -6
  122. data/spec/lib/{orm/active_record/stale_records_cleaner_spec.rb → stale_records_cleaner_spec.rb} +14 -4
  123. data/spec/models/doorkeeper/access_token_spec.rb +14 -10
  124. data/spec/models/doorkeeper/application_spec.rb +4 -4
  125. data/spec/requests/applications/applications_request_spec.rb +2 -2
  126. data/spec/requests/endpoints/authorization_spec.rb +2 -2
  127. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
  128. data/spec/requests/flows/authorization_code_spec.rb +75 -15
  129. data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
  130. data/spec/requests/flows/password_spec.rb +6 -2
  131. data/spec/requests/flows/refresh_token_spec.rb +57 -0
  132. data/spec/requests/flows/revoke_token_spec.rb +9 -9
  133. data/spec/requests/protected_resources/private_api_spec.rb +2 -2
  134. data/spec/support/doorkeeper_rspec.rb +2 -1
  135. data/spec/support/helpers/model_helper.rb +8 -4
  136. data/spec/support/helpers/url_helper.rb +11 -11
  137. data/spec/support/shared/controllers_shared_context.rb +56 -0
  138. data/spec/validators/redirect_uri_validator_spec.rb +2 -2
  139. metadata +20 -4
@@ -210,10 +210,10 @@ module Doorkeeper
210
210
  it 'revokes all access tokens and access grants' do
211
211
  application_id = 42
212
212
  resource_owner = double
213
- expect(Doorkeeper::AccessToken).
214
- to receive(:revoke_all_for).with(application_id, resource_owner)
215
- expect(Doorkeeper::AccessGrant).
216
- to receive(:revoke_all_for).with(application_id, resource_owner)
213
+ expect(Doorkeeper::AccessToken)
214
+ .to receive(:revoke_all_for).with(application_id, resource_owner)
215
+ expect(Doorkeeper::AccessGrant)
216
+ .to receive(:revoke_all_for).with(application_id, resource_owner)
217
217
 
218
218
  Application.revoke_tokens_and_grants_for(application_id, resource_owner)
219
219
  end
@@ -62,7 +62,7 @@ feature 'Adding applications' do
62
62
 
63
63
  scenario "adding app validating scope, multiple scopes configured" do
64
64
  config_is_set("enforce_configured_scopes", true)
65
- scopes = Doorkeeper::OAuth::Scopes.from_array(%w(read write admin))
65
+ scopes = Doorkeeper::OAuth::Scopes.from_array(%w[read write admin])
66
66
  config_is_set("optional_scopes", scopes)
67
67
 
68
68
  fill_in "doorkeeper_application[name]", with: "My Application"
@@ -77,7 +77,7 @@ feature 'Adding applications' do
77
77
 
78
78
  scenario "adding app validating scope, bad scope with multiple scopes configured" do
79
79
  config_is_set("enforce_configured_scopes", true)
80
- scopes = Doorkeeper::OAuth::Scopes.from_array(%w(read write admin))
80
+ scopes = Doorkeeper::OAuth::Scopes.from_array(%w[read write admin])
81
81
  config_is_set("optional_scopes", scopes)
82
82
 
83
83
  fill_in "doorkeeper_application[name]", with: "My Application"
@@ -60,11 +60,11 @@ feature 'Authorization endpoint' do
60
60
 
61
61
  scenario 'raises exception on forged requests' do
62
62
  allowing_forgery_protection do
63
- expect {
63
+ expect do
64
64
  page.driver.post authorization_endpoint_url(client_id: @client.uid,
65
65
  redirect_uri: @client.redirect_uri,
66
66
  response_type: 'code')
67
- }.to raise_error(ActionController::InvalidAuthenticityToken)
67
+ end.to raise_error(ActionController::InvalidAuthenticityToken)
68
68
  end
69
69
  end
70
70
  end
@@ -57,7 +57,7 @@ describe 'Authorization Code Flow Errors', 'after authorization' do
57
57
  # Second attempt with same token
58
58
  expect do
59
59
  post token_endpoint_url(code: @authorization.token, client: @client)
60
- end.to_not change { Doorkeeper::AccessToken.count }
60
+ end.to_not(change { Doorkeeper::AccessToken.count })
61
61
 
62
62
  should_not_have_json 'access_token'
63
63
  should_have_json 'error', 'invalid_grant'
@@ -66,18 +66,36 @@ feature 'Authorization Code Flow' do
66
66
  page.driver.post token_endpoint_url(code: authorization_code, client_id: @client.uid,
67
67
  redirect_uri: @client.redirect_uri)
68
68
 
69
- expect(Doorkeeper::AccessToken).not_to exist
69
+ expect(Doorkeeper::AccessToken.count).to be_zero
70
70
 
71
71
  should_have_json 'error', 'invalid_client'
72
72
  end
73
73
 
74
+ scenario 'silently authorizes if matching token exists' do
75
+ default_scopes_exist :public, :write
76
+
77
+ access_token_exists application: @client,
78
+ expires_in: -100, # even expired token
79
+ resource_owner_id: @resource_owner.id,
80
+ scopes: 'public write'
81
+
82
+ visit authorization_endpoint_url(client: @client, scope: 'public write')
83
+
84
+ response_status_should_be 200
85
+ i_should_not_see 'Authorize'
86
+ end
87
+
74
88
  context 'with PKCE' do
75
89
  context 'plain' do
76
90
  let(:code_challenge) { 'a45a9fea-0676-477e-95b1-a40f72ac3cfb' }
77
91
  let(:code_verifier) { 'a45a9fea-0676-477e-95b1-a40f72ac3cfb' }
78
92
 
79
93
  scenario 'resource owner authorizes the client with code_challenge parameter set' do
80
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: 'plain')
94
+ visit authorization_endpoint_url(
95
+ client: @client,
96
+ code_challenge: code_challenge,
97
+ code_challenge_method: 'plain'
98
+ )
81
99
  click_on 'Authorize'
82
100
 
83
101
  url_should_have_param('code', Doorkeeper::AccessGrant.first.token)
@@ -96,7 +114,11 @@ feature 'Authorization Code Flow' do
96
114
  end
97
115
 
98
116
  scenario 'mobile app requests an access token with authorization code and plain code challenge method' do
99
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: 'plain')
117
+ visit authorization_endpoint_url(
118
+ client: @client,
119
+ code_challenge: code_challenge,
120
+ code_challenge_method: 'plain'
121
+ )
100
122
  click_on 'Authorize'
101
123
 
102
124
  authorization_code = current_params['code']
@@ -130,7 +152,11 @@ feature 'Authorization Code Flow' do
130
152
  let(:code_verifier) { 'a45a9fea-0676-477e-95b1-a40f72ac3cfb' }
131
153
 
132
154
  scenario 'resource owner authorizes the client with code_challenge parameter set' do
133
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: 'S256')
155
+ visit authorization_endpoint_url(
156
+ client: @client,
157
+ code_challenge: code_challenge,
158
+ code_challenge_method: 'S256'
159
+ )
134
160
  click_on 'Authorize'
135
161
 
136
162
  url_should_have_param('code', Doorkeeper::AccessGrant.first.token)
@@ -139,7 +165,11 @@ feature 'Authorization Code Flow' do
139
165
  end
140
166
 
141
167
  scenario 'mobile app requests an access token with authorization code and S256 code challenge method' do
142
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: 'S256')
168
+ visit authorization_endpoint_url(
169
+ client: @client,
170
+ code_challenge: code_challenge,
171
+ code_challenge_method: 'S256'
172
+ )
143
173
  click_on 'Authorize'
144
174
 
145
175
  authorization_code = current_params['code']
@@ -155,7 +185,11 @@ feature 'Authorization Code Flow' do
155
185
  end
156
186
 
157
187
  scenario 'mobile app requests an access token with authorization code and without code_verifier' do
158
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: 'S256')
188
+ visit authorization_endpoint_url(
189
+ client: @client,
190
+ code_challenge: code_challenge,
191
+ code_challenge_method: 'S256'
192
+ )
159
193
  click_on 'Authorize'
160
194
  authorization_code = current_params['code']
161
195
  create_access_token authorization_code, @client
@@ -164,7 +198,11 @@ feature 'Authorization Code Flow' do
164
198
  end
165
199
 
166
200
  scenario 'mobile app requests an access token with authorization code and without secret' do
167
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: 'S256')
201
+ visit authorization_endpoint_url(
202
+ client: @client,
203
+ code_challenge: code_challenge,
204
+ code_challenge_method: 'S256'
205
+ )
168
206
  click_on 'Authorize'
169
207
 
170
208
  authorization_code = current_params['code']
@@ -180,8 +218,12 @@ feature 'Authorization Code Flow' do
180
218
  click_on 'Authorize'
181
219
 
182
220
  authorization_code = current_params['code']
183
- page.driver.post token_endpoint_url(code: authorization_code, client_id: @client.uid,
184
- redirect_uri: @client.redirect_uri, code_verifier: code_verifier)
221
+ page.driver.post token_endpoint_url(
222
+ code: authorization_code,
223
+ client_id: @client.uid,
224
+ redirect_uri: @client.redirect_uri,
225
+ code_verifier: code_verifier
226
+ )
185
227
  should_not_have_json 'error'
186
228
 
187
229
  should_have_json 'access_token', Doorkeeper::AccessToken.first.token
@@ -190,7 +232,11 @@ feature 'Authorization Code Flow' do
190
232
  end
191
233
 
192
234
  scenario 'mobile app requests an access token with authorization code but no code verifier' do
193
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: 'S256')
235
+ visit authorization_endpoint_url(
236
+ client: @client,
237
+ code_challenge: code_challenge,
238
+ code_challenge_method: 'S256'
239
+ )
194
240
  click_on 'Authorize'
195
241
 
196
242
  authorization_code = current_params['code']
@@ -201,7 +247,11 @@ feature 'Authorization Code Flow' do
201
247
  end
202
248
 
203
249
  scenario 'mobile app requests an access token with authorization code with wrong verifier' do
204
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: 'S256')
250
+ visit authorization_endpoint_url(
251
+ client: @client,
252
+ code_challenge: code_challenge,
253
+ code_challenge_method: 'S256'
254
+ )
205
255
  click_on 'Authorize'
206
256
 
207
257
  authorization_code = current_params['code']
@@ -212,12 +262,20 @@ feature 'Authorization Code Flow' do
212
262
  end
213
263
 
214
264
  scenario 'code_challenge_mehthod in token request is totally ignored' do
215
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: 'S256')
265
+ visit authorization_endpoint_url(
266
+ client: @client,
267
+ code_challenge: code_challenge,
268
+ code_challenge_method: 'S256'
269
+ )
216
270
  click_on 'Authorize'
217
271
 
218
272
  authorization_code = current_params['code']
219
- page.driver.post token_endpoint_url(code: authorization_code, client: @client, code_verifier: code_challenge,
220
- code_challenge_method: 'plain')
273
+ page.driver.post token_endpoint_url(
274
+ code: authorization_code,
275
+ client: @client,
276
+ code_verifier: code_challenge,
277
+ code_challenge_method: 'plain'
278
+ )
221
279
 
222
280
  should_not_have_json 'access_token'
223
281
  should_have_json 'error', 'invalid_grant'
@@ -324,6 +382,7 @@ describe 'Authorization Code Flow' do
324
382
  orm DOORKEEPER_ORM
325
383
  use_refresh_token
326
384
  end
385
+
327
386
  client_exists
328
387
  end
329
388
 
@@ -334,7 +393,8 @@ describe 'Authorization Code Flow' do
334
393
 
335
394
  it 'second of simultaneous client requests get an error for revoked acccess token' do
336
395
  authorization_code = Doorkeeper::AccessGrant.first.token
337
- allow_any_instance_of(Doorkeeper::AccessGrant).to receive(:revoked?).and_return(false, true)
396
+ allow_any_instance_of(Doorkeeper::AccessGrant)
397
+ .to receive(:revoked?).and_return(false, true)
338
398
 
339
399
  post token_endpoint_url(code: authorization_code, client: @client)
340
400
 
@@ -14,8 +14,8 @@ feature 'Implicit Grant Flow Errors' do
14
14
  end
15
15
 
16
16
  [
17
- [:client_id, :invalid_client],
18
- [:redirect_uri, :invalid_redirect_uri]
17
+ %i[client_id invalid_client],
18
+ %i[redirect_uri invalid_redirect_uri]
19
19
  ].each do |error|
20
20
  scenario "displays #{error.last} error for invalid #{error.first}" do
21
21
  visit authorization_endpoint_url(client: @client, error.first => 'invalid', response_type: 'token')
@@ -57,7 +57,11 @@ describe 'Resource Owner Password Credentials Flow' do
57
57
  context "when client_secret incorrect" do
58
58
  it "should not issue new token" do
59
59
  expect do
60
- post password_token_endpoint_url(client_id: @client.uid, client_secret: 'foobar', resource_owner: @resource_owner)
60
+ post password_token_endpoint_url(
61
+ client_id: @client.uid,
62
+ client_secret: 'foobar',
63
+ resource_owner: @resource_owner
64
+ )
61
65
  end.not_to(change { Doorkeeper::AccessToken.count })
62
66
 
63
67
  expect(response).not_to be_ok
@@ -148,7 +152,7 @@ describe 'Resource Owner Password Credentials Flow' do
148
152
 
149
153
  it 'issues new token without any scope' do
150
154
  expect do
151
- post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
155
+ post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
152
156
  end.to change { Doorkeeper::AccessToken.count }.by(1)
153
157
 
154
158
  token = Doorkeeper::AccessToken.first
@@ -6,6 +6,7 @@ describe 'Refresh Token Flow' do
6
6
  orm DOORKEEPER_ORM
7
7
  use_refresh_token
8
8
  end
9
+
9
10
  client_exists
10
11
  end
11
12
 
@@ -95,6 +96,62 @@ describe 'Refresh Token Flow' do
95
96
  end
96
97
  end
97
98
 
99
+ context "public & private clients" do
100
+ let(:public_client) do
101
+ FactoryBot.create(
102
+ :application,
103
+ confidential: false
104
+ )
105
+ end
106
+
107
+ let(:token_for_private_client) do
108
+ FactoryBot.create(
109
+ :access_token,
110
+ application: @client,
111
+ resource_owner_id: 1,
112
+ use_refresh_token: true
113
+ )
114
+ end
115
+
116
+ let(:token_for_public_client) do
117
+ FactoryBot.create(
118
+ :access_token,
119
+ application: public_client,
120
+ resource_owner_id: 1,
121
+ use_refresh_token: true
122
+ )
123
+ end
124
+
125
+ it 'issues a new token without client_secret when refresh token was issued to a public client' do
126
+ post refresh_token_endpoint_url(
127
+ client_id: public_client.uid,
128
+ refresh_token: token_for_public_client.refresh_token
129
+ )
130
+
131
+ new_token = Doorkeeper::AccessToken.last
132
+ should_have_json 'access_token', new_token.token
133
+ should_have_json 'refresh_token', new_token.refresh_token
134
+ end
135
+
136
+ it 'returns an error without credentials' do
137
+ post refresh_token_endpoint_url(refresh_token: token_for_private_client.refresh_token)
138
+
139
+ should_not_have_json 'refresh_token'
140
+ should_have_json 'error', 'invalid_grant'
141
+ end
142
+
143
+ it 'returns an error with wrong credentials' do
144
+ post refresh_token_endpoint_url(
145
+ client_id: '1',
146
+ client_secret: '1',
147
+ refresh_token: token_for_private_client.refresh_token
148
+ )
149
+
150
+ should_not_have_json 'refresh_token'
151
+ should_have_json 'error', 'invalid_client'
152
+ end
153
+ end
154
+
98
155
  it 'client gets an error for invalid refresh token' do
99
156
  post refresh_token_endpoint_url(client: @client, refresh_token: 'invalid')
100
157
  should_not_have_json 'refresh_token'
@@ -10,9 +10,9 @@ describe 'Revoke Token Flow' do
10
10
  let(:resource_owner) { User.create!(name: 'John', password: 'sekret') }
11
11
  let(:access_token) do
12
12
  FactoryBot.create(:access_token,
13
- application: client_application,
14
- resource_owner_id: resource_owner.id,
15
- use_refresh_token: true)
13
+ application: client_application,
14
+ resource_owner_id: resource_owner.id,
15
+ use_refresh_token: true)
16
16
  end
17
17
 
18
18
  context 'with authenticated, confidential OAuth 2.0 client/application' do
@@ -103,9 +103,9 @@ describe 'Revoke Token Flow' do
103
103
  context 'with public OAuth 2.0 client/application' do
104
104
  let(:access_token) do
105
105
  FactoryBot.create(:access_token,
106
- application: nil,
107
- resource_owner_id: resource_owner.id,
108
- use_refresh_token: true)
106
+ application: nil,
107
+ resource_owner_id: resource_owner.id,
108
+ use_refresh_token: true)
109
109
  end
110
110
 
111
111
  it 'should revoke the access token provided' do
@@ -129,9 +129,9 @@ describe 'Revoke Token Flow' do
129
129
  context 'with a valid token issued for a confidential client' do
130
130
  let(:access_token) do
131
131
  FactoryBot.create(:access_token,
132
- application: client_application,
133
- resource_owner_id: resource_owner.id,
134
- use_refresh_token: true)
132
+ application: client_application,
133
+ resource_owner_id: resource_owner.id,
134
+ use_refresh_token: true)
135
135
  end
136
136
 
137
137
  it 'should not revoke the access token provided' do
@@ -41,10 +41,10 @@ feature 'Private API' do
41
41
  end
42
42
 
43
43
  scenario 'access token with no default scopes' do
44
- Doorkeeper.configuration.instance_eval {
44
+ Doorkeeper.configuration.instance_eval do
45
45
  @default_scopes = Doorkeeper::OAuth::Scopes.from_array([:public])
46
46
  @scopes = default_scopes + optional_scopes
47
- }
47
+ end
48
48
  @token.update_attribute :scopes, 'dummy'
49
49
  with_access_token_header @token.token
50
50
  visit '/full_protected_resources'
@@ -4,7 +4,8 @@ module Doorkeeper
4
4
  # Doorkeeper configuration, etc.
5
5
  def self.print_configuration_info
6
6
  puts <<-INFO.strip_heredoc
7
- ====> Doorkeeper ORM = #{Doorkeeper.configuration.orm}
7
+ ====> Doorkeeper ORM: '#{Doorkeeper.configuration.orm}'
8
+ ====> Doorkeeper version: #{Doorkeeper.gem_version}
8
9
  ====> Rails version: #{::Rails.version}
9
10
  ====> Ruby version: #{RUBY_VERSION} on #{RUBY_PLATFORM}
10
11
  INFO
@@ -11,11 +11,15 @@ module ModelHelper
11
11
  @authorization = FactoryBot.create(:access_grant, options)
12
12
  end
13
13
 
14
+ def access_token_exists(options = {})
15
+ @access_token = FactoryBot.create(:access_token, options)
16
+ end
17
+
14
18
  def access_grant_should_exist_for(client, resource_owner)
15
19
  grant = Doorkeeper::AccessGrant.first
16
20
 
17
- expect(grant.application).to have_attributes(id: client.id).
18
- and(be_instance_of(Doorkeeper::Application))
21
+ expect(grant.application).to have_attributes(id: client.id)
22
+ .and(be_instance_of(Doorkeeper::Application))
19
23
 
20
24
  expect(grant.resource_owner_id).to eq(resource_owner.id)
21
25
  end
@@ -23,8 +27,8 @@ module ModelHelper
23
27
  def access_token_should_exist_for(client, resource_owner)
24
28
  token = Doorkeeper::AccessToken.first
25
29
 
26
- expect(token.application).to have_attributes(id: client.id).
27
- and(be_instance_of(Doorkeeper::Application))
30
+ expect(token.application).to have_attributes(id: client.id)
31
+ .and(be_instance_of(Doorkeeper::Application))
28
32
 
29
33
  expect(token.resource_owner_id).to eq(resource_owner.id)
30
34
  end
@@ -2,9 +2,9 @@ module UrlHelper
2
2
  def token_endpoint_url(options = {})
3
3
  parameters = {
4
4
  code: options[:code],
5
- client_id: options[:client_id] || (options[:client] ? options[:client].uid : nil),
6
- client_secret: options[:client_secret] || (options[:client] ? options[:client].secret : nil),
7
- redirect_uri: options[:redirect_uri] || (options[:client] ? options[:client].redirect_uri : nil),
5
+ client_id: options[:client_id] || options[:client].try(:uid),
6
+ client_secret: options[:client_secret] || options[:client].try(:secret),
7
+ redirect_uri: options[:redirect_uri] || options[:client].try(:redirect_uri),
8
8
  grant_type: options[:grant_type] || 'authorization_code',
9
9
  code_verifier: options[:code_verifier],
10
10
  code_challenge_method: options[:code_challenge_method]
@@ -15,10 +15,10 @@ module UrlHelper
15
15
  def password_token_endpoint_url(options = {})
16
16
  parameters = {
17
17
  code: options[:code],
18
- client_id: options[:client_id] || (options[:client] ? options[:client].uid : nil),
19
- client_secret: options[:client_secret] || (options[:client] ? options[:client].secret : nil),
20
- username: options[:resource_owner_username] || (options[:resource_owner] ? options[:resource_owner].name : nil),
21
- password: options[:resource_owner_password] || (options[:resource_owner] ? options[:resource_owner].password : nil),
18
+ client_id: options[:client_id] || options[:client].try(:uid),
19
+ client_secret: options[:client_secret] || options[:client].try(:secret),
20
+ username: options[:resource_owner_username] || options[:resource_owner].try(:name),
21
+ password: options[:resource_owner_password] || options[:resource_owner].try(:password),
22
22
  scope: options[:scope],
23
23
  grant_type: 'password'
24
24
  }
@@ -27,8 +27,8 @@ module UrlHelper
27
27
 
28
28
  def authorization_endpoint_url(options = {})
29
29
  parameters = {
30
- client_id: options[:client_id] || options[:client].uid,
31
- redirect_uri: options[:redirect_uri] || options[:client].redirect_uri,
30
+ client_id: options[:client_id] || options[:client].try(:uid),
31
+ redirect_uri: options[:redirect_uri] || options[:client].try(:redirect_uri),
32
32
  response_type: options[:response_type] || 'code',
33
33
  scope: options[:scope],
34
34
  state: options[:state],
@@ -41,8 +41,8 @@ module UrlHelper
41
41
  def refresh_token_endpoint_url(options = {})
42
42
  parameters = {
43
43
  refresh_token: options[:refresh_token],
44
- client_id: options[:client_id] || options[:client].uid,
45
- client_secret: options[:client_secret] || options[:client].secret,
44
+ client_id: options[:client_id] || options[:client].try(:uid),
45
+ client_secret: options[:client_secret] || options[:client].try(:secret),
46
46
  grant_type: options[:grant_type] || 'refresh_token'
47
47
  }
48
48
  "/oauth/token?#{build_query(parameters)}"