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.
- checksums.yaml +5 -5
- data/.travis.yml +17 -4
- data/Appraisals +29 -3
- data/Dangerfile +5 -2
- data/Gemfile +14 -4
- data/NEWS.md +64 -19
- data/README.md +68 -487
- data/app/controllers/doorkeeper/token_info_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +7 -7
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
- data/bin/console +15 -0
- data/doorkeeper.gemspec +3 -2
- data/gemfiles/rails_4_2.gemfile +8 -4
- data/gemfiles/rails_5_0.gemfile +9 -5
- data/gemfiles/rails_5_1.gemfile +9 -5
- data/gemfiles/rails_5_2.gemfile +9 -5
- data/gemfiles/rails_6_0.gemfile +16 -0
- data/gemfiles/rails_master.gemfile +8 -9
- data/lib/doorkeeper/config.rb +164 -11
- data/lib/doorkeeper/helpers/controller.rb +3 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +16 -1
- data/lib/doorkeeper/models/access_token_mixin.rb +54 -10
- data/lib/doorkeeper/models/application_mixin.rb +42 -1
- data/lib/doorkeeper/models/concerns/expirable.rb +3 -2
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/token.rb +4 -2
- data/lib/doorkeeper/oauth/authorization_code_request.rb +1 -1
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -3
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +5 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +12 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +32 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +4 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +8 -3
- data/lib/doorkeeper/oauth/refresh_token_request.rb +4 -1
- data/lib/doorkeeper/oauth/token_introspection.rb +72 -6
- data/lib/doorkeeper/oauth/token_response.rb +2 -2
- data/lib/doorkeeper/orm/active_record/access_grant.rb +23 -2
- data/lib/doorkeeper/orm/active_record/application.rb +20 -2
- data/lib/doorkeeper/secret_storing/base.rb +63 -0
- data/lib/doorkeeper/secret_storing/bcrypt.rb +59 -0
- data/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +25 -0
- data/lib/doorkeeper/version.rb +3 -3
- data/lib/doorkeeper.rb +7 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +90 -8
- data/spec/controllers/application_metal_controller_spec.rb +18 -4
- data/spec/controllers/authorizations_controller_spec.rb +3 -3
- data/spec/controllers/token_info_controller_spec.rb +1 -1
- data/spec/controllers/tokens_controller_spec.rb +85 -41
- data/spec/dummy/app/controllers/application_controller.rb +1 -1
- data/spec/dummy/config/application.rb +12 -1
- data/spec/factories.rb +3 -3
- data/spec/lib/config_spec.rb +168 -0
- data/spec/lib/models/expirable_spec.rb +12 -0
- data/spec/lib/models/reusable_spec.rb +40 -0
- data/spec/lib/models/scopes_spec.rb +13 -1
- data/spec/lib/models/secret_storable_spec.rb +113 -0
- data/spec/lib/oauth/authorization_code_request_spec.rb +18 -1
- data/spec/lib/oauth/base_request_spec.rb +7 -7
- data/spec/lib/oauth/client_credentials/creator_spec.rb +51 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +3 -0
- data/spec/lib/oauth/error_response_spec.rb +7 -1
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +52 -17
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +20 -2
- data/spec/lib/oauth/password_access_token_request_spec.rb +43 -12
- data/spec/lib/oauth/pre_authorization_spec.rb +24 -0
- data/spec/lib/oauth/token_request_spec.rb +16 -1
- data/spec/lib/oauth/token_response_spec.rb +13 -13
- data/spec/lib/oauth/token_spec.rb +14 -0
- data/spec/lib/secret_storing/base_spec.rb +60 -0
- data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
- data/spec/lib/secret_storing/plain_spec.rb +44 -0
- data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +61 -0
- data/spec/models/doorkeeper/access_token_spec.rb +123 -0
- data/spec/models/doorkeeper/application_spec.rb +56 -0
- data/spec/requests/flows/authorization_code_spec.rb +41 -1
- data/spec/requests/flows/client_credentials_spec.rb +2 -2
- data/spec/requests/flows/implicit_grant_spec.rb +1 -1
- data/spec/requests/flows/password_spec.rb +7 -5
- data/spec/requests/flows/revoke_token_spec.rb +14 -30
- data/spec/routing/custom_controller_routes_spec.rb +4 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/ruby_2_6_rails_4_2_patch.rb +14 -0
- data/spec/support/shared/hashing_shared_context.rb +36 -0
- metadata +59 -22
|
@@ -20,7 +20,7 @@ describe Doorkeeper::TokensController do
|
|
|
20
20
|
|
|
21
21
|
post :create
|
|
22
22
|
|
|
23
|
-
expect(response.status).to eq
|
|
23
|
+
expect(response.status).to eq 400
|
|
24
24
|
expect(response.headers['WWW-Authenticate']).to match(/Bearer/)
|
|
25
25
|
end
|
|
26
26
|
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 =
|
|
31
|
+
custom_message = 'my_message'
|
|
32
32
|
allow(I18n).to receive(:translate)
|
|
33
33
|
.with(
|
|
34
34
|
custom_message,
|
|
@@ -49,7 +49,7 @@ describe Doorkeeper::TokensController do
|
|
|
49
49
|
"error" => custom_message,
|
|
50
50
|
"error_description" => "Authorization custom message"
|
|
51
51
|
}
|
|
52
|
-
expect(response.status).to eq
|
|
52
|
+
expect(response.status).to eq 400
|
|
53
53
|
expect(response.headers['WWW-Authenticate']).to match(/Bearer/)
|
|
54
54
|
expect(JSON.parse(response.body)).to eq expected_response_body
|
|
55
55
|
end
|
|
@@ -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
|
|
@@ -134,28 +130,26 @@ describe Doorkeeper::TokensController do
|
|
|
134
130
|
end
|
|
135
131
|
|
|
136
132
|
describe 'when requested token introspection' do
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
let(:client) { FactoryBot.create(:application) }
|
|
134
|
+
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
135
|
+
let(:token_for_introspection) { FactoryBot.create(:access_token, application: client) }
|
|
140
136
|
|
|
137
|
+
context 'authorized using valid Bearer token' do
|
|
141
138
|
it 'responds with full token introspection' do
|
|
142
139
|
request.headers['Authorization'] = "Bearer #{access_token.token}"
|
|
143
140
|
|
|
144
|
-
post :introspect, params: { token:
|
|
141
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
145
142
|
|
|
146
143
|
should_have_json 'active', true
|
|
147
144
|
expect(json_response).to include('client_id', 'token_type', 'exp', 'iat')
|
|
148
145
|
end
|
|
149
146
|
end
|
|
150
147
|
|
|
151
|
-
context 'authorized using Client Authentication' do
|
|
152
|
-
let(:client) { FactoryBot.create(:application) }
|
|
153
|
-
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
154
|
-
|
|
148
|
+
context 'authorized using valid Client Authentication' do
|
|
155
149
|
it 'responds with full token introspection' do
|
|
156
150
|
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
157
151
|
|
|
158
|
-
post :introspect, params: { token:
|
|
152
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
159
153
|
|
|
160
154
|
should_have_json 'active', true
|
|
161
155
|
expect(json_response).to include('client_id', 'token_type', 'exp', 'iat')
|
|
@@ -163,14 +157,37 @@ describe Doorkeeper::TokensController do
|
|
|
163
157
|
end
|
|
164
158
|
end
|
|
165
159
|
|
|
160
|
+
context 'using custom introspection response' do
|
|
161
|
+
before do
|
|
162
|
+
Doorkeeper.configure do
|
|
163
|
+
orm DOORKEEPER_ORM
|
|
164
|
+
custom_introspection_response do |_token, _context|
|
|
165
|
+
{
|
|
166
|
+
sub: 'Z5O3upPC88QrAjx00dis',
|
|
167
|
+
aud: 'https://protected.example.net/resource'
|
|
168
|
+
}
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it 'responds with full token introspection' do
|
|
174
|
+
request.headers['Authorization'] = "Bearer #{access_token.token}"
|
|
175
|
+
|
|
176
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
177
|
+
|
|
178
|
+
expect(json_response).to include('client_id', 'token_type', 'exp', 'iat', 'sub', 'aud')
|
|
179
|
+
should_have_json 'sub', 'Z5O3upPC88QrAjx00dis'
|
|
180
|
+
should_have_json 'aud', 'https://protected.example.net/resource'
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
166
184
|
context 'public access token' do
|
|
167
|
-
let(:
|
|
168
|
-
let(:access_token) { FactoryBot.create(:access_token, application: nil) }
|
|
185
|
+
let(:token_for_introspection) { FactoryBot.create(:access_token, application: nil) }
|
|
169
186
|
|
|
170
187
|
it 'responds with full token introspection' do
|
|
171
188
|
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
172
189
|
|
|
173
|
-
post :introspect, params: { token:
|
|
190
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
174
191
|
|
|
175
192
|
should_have_json 'active', true
|
|
176
193
|
expect(json_response).to include('client_id', 'token_type', 'exp', 'iat')
|
|
@@ -179,14 +196,12 @@ describe Doorkeeper::TokensController do
|
|
|
179
196
|
end
|
|
180
197
|
|
|
181
198
|
context 'token was issued to a different client than is making this request' do
|
|
182
|
-
let(:client) { FactoryBot.create(:application) }
|
|
183
199
|
let(:different_client) { FactoryBot.create(:application) }
|
|
184
|
-
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
185
200
|
|
|
186
201
|
it 'responds with only active state' do
|
|
187
202
|
request.headers['Authorization'] = basic_auth_header_for_client(different_client)
|
|
188
203
|
|
|
189
|
-
post :introspect, params: { token:
|
|
204
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
190
205
|
|
|
191
206
|
expect(response).to be_successful
|
|
192
207
|
|
|
@@ -195,6 +210,36 @@ describe Doorkeeper::TokensController do
|
|
|
195
210
|
end
|
|
196
211
|
end
|
|
197
212
|
|
|
213
|
+
context 'authorized using invalid Bearer token' do
|
|
214
|
+
let(:token_for_introspection) do
|
|
215
|
+
FactoryBot.create(:access_token, application: client, revoked_at: 1.day.ago)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it 'responds with invalid token error' do
|
|
219
|
+
request.headers['Authorization'] = "Bearer #{token_for_introspection.token}"
|
|
220
|
+
|
|
221
|
+
post :introspect, params: { token: access_token.token }
|
|
222
|
+
|
|
223
|
+
response_status_should_be 401
|
|
224
|
+
|
|
225
|
+
should_not_have_json 'active'
|
|
226
|
+
should_have_json 'error', 'invalid_token'
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
context 'authorized using the Bearer token that need to be introspected' do
|
|
231
|
+
it 'responds with invalid token error' do
|
|
232
|
+
request.headers['Authorization'] = "Bearer #{access_token.token}"
|
|
233
|
+
|
|
234
|
+
post :introspect, params: { token: access_token.token }
|
|
235
|
+
|
|
236
|
+
response_status_should_be 401
|
|
237
|
+
|
|
238
|
+
should_not_have_json 'active'
|
|
239
|
+
should_have_json 'error', 'invalid_token'
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
198
243
|
context 'using invalid credentials to authorize' do
|
|
199
244
|
let(:client) { double(uid: '123123', secret: '666999') }
|
|
200
245
|
let(:access_token) { FactoryBot.create(:access_token) }
|
|
@@ -213,9 +258,6 @@ describe Doorkeeper::TokensController do
|
|
|
213
258
|
end
|
|
214
259
|
|
|
215
260
|
context 'using wrong token value' do
|
|
216
|
-
let(:client) { FactoryBot.create(:application) }
|
|
217
|
-
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
218
|
-
|
|
219
261
|
it 'responds with only active state' do
|
|
220
262
|
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
221
263
|
|
|
@@ -226,14 +268,15 @@ describe Doorkeeper::TokensController do
|
|
|
226
268
|
end
|
|
227
269
|
end
|
|
228
270
|
|
|
229
|
-
context 'when requested
|
|
230
|
-
let(:
|
|
231
|
-
|
|
271
|
+
context 'when requested access token expired' do
|
|
272
|
+
let(:token_for_introspection) do
|
|
273
|
+
FactoryBot.create(:access_token, application: client, created_at: 1.year.ago)
|
|
274
|
+
end
|
|
232
275
|
|
|
233
276
|
it 'responds with only active state' do
|
|
234
277
|
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
235
278
|
|
|
236
|
-
post :introspect, params: { token:
|
|
279
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
237
280
|
|
|
238
281
|
should_have_json 'active', false
|
|
239
282
|
expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
|
|
@@ -241,13 +284,14 @@ describe Doorkeeper::TokensController do
|
|
|
241
284
|
end
|
|
242
285
|
|
|
243
286
|
context 'when requested Access Token revoked' do
|
|
244
|
-
let(:
|
|
245
|
-
|
|
287
|
+
let(:token_for_introspection) do
|
|
288
|
+
FactoryBot.create(:access_token, application: client, revoked_at: 1.year.ago)
|
|
289
|
+
end
|
|
246
290
|
|
|
247
291
|
it 'responds with only active state' do
|
|
248
292
|
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
249
293
|
|
|
250
|
-
post :introspect, params: { token:
|
|
294
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
251
295
|
|
|
252
296
|
should_have_json 'active', false
|
|
253
297
|
expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
|
|
@@ -255,13 +299,13 @@ describe Doorkeeper::TokensController do
|
|
|
255
299
|
end
|
|
256
300
|
|
|
257
301
|
context 'unauthorized (no bearer token or client credentials)' do
|
|
258
|
-
let(:
|
|
302
|
+
let(:token_for_introspection) { FactoryBot.create(:access_token) }
|
|
259
303
|
|
|
260
304
|
it 'responds with invalid_request error' do
|
|
261
|
-
post :introspect, params: { token:
|
|
305
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
262
306
|
|
|
263
307
|
expect(response).not_to be_successful
|
|
264
|
-
response_status_should_be
|
|
308
|
+
response_status_should_be 400
|
|
265
309
|
|
|
266
310
|
should_not_have_json 'active'
|
|
267
311
|
should_have_json 'error', 'invalid_request'
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
require File.expand_path('boot', __dir__)
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rails"
|
|
4
|
+
|
|
5
|
+
%w[
|
|
6
|
+
action_controller/railtie
|
|
7
|
+
action_view/railtie
|
|
8
|
+
sprockets/railtie
|
|
9
|
+
].each do |railtie|
|
|
10
|
+
begin
|
|
11
|
+
require railtie
|
|
12
|
+
rescue LoadError
|
|
13
|
+
end
|
|
14
|
+
end
|
|
4
15
|
|
|
5
16
|
Bundler.require(*Rails.groups)
|
|
6
17
|
|
data/spec/factories.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
FactoryBot.define do
|
|
2
|
-
factory :access_grant, class: Doorkeeper::AccessGrant do
|
|
2
|
+
factory :access_grant, class: "Doorkeeper::AccessGrant" do
|
|
3
3
|
sequence(:resource_owner_id) { |n| n }
|
|
4
4
|
application
|
|
5
5
|
redirect_uri { 'https://app.com/callback' }
|
|
@@ -7,7 +7,7 @@ FactoryBot.define do
|
|
|
7
7
|
scopes { 'public write' }
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
factory :access_token, class: Doorkeeper::AccessToken do
|
|
10
|
+
factory :access_token, class: "Doorkeeper::AccessToken" do
|
|
11
11
|
sequence(:resource_owner_id) { |n| n }
|
|
12
12
|
application
|
|
13
13
|
expires_in { 2.hours }
|
|
@@ -17,7 +17,7 @@ FactoryBot.define do
|
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
factory :application, class: Doorkeeper::Application do
|
|
20
|
+
factory :application, class: "Doorkeeper::Application" do
|
|
21
21
|
sequence(:name) { |n| "Application #{n}" }
|
|
22
22
|
redirect_uri { 'https://app.com/callback' }
|
|
23
23
|
end
|
data/spec/lib/config_spec.rb
CHANGED
|
@@ -141,6 +141,22 @@ describe Doorkeeper, 'configuration' do
|
|
|
141
141
|
end
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
+
describe 'scopes_by_grant_type' do
|
|
145
|
+
it 'is {} by default' do
|
|
146
|
+
expect(subject.scopes_by_grant_type).to eq({})
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'has hash value' do
|
|
150
|
+
hash = {}
|
|
151
|
+
Doorkeeper.configure do
|
|
152
|
+
orm DOORKEEPER_ORM
|
|
153
|
+
scopes_by_grant_type hash
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
expect(subject.scopes_by_grant_type).to eq(hash)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
144
160
|
describe 'use_refresh_token' do
|
|
145
161
|
it 'is false by default' do
|
|
146
162
|
expect(subject.refresh_token_enabled?).to eq(false)
|
|
@@ -191,6 +207,31 @@ describe Doorkeeper, 'configuration' do
|
|
|
191
207
|
end
|
|
192
208
|
end
|
|
193
209
|
|
|
210
|
+
describe 'token_reuse_limit' do
|
|
211
|
+
it 'is 100 by default' do
|
|
212
|
+
expect(subject.token_reuse_limit).to eq(100)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it 'can change the value' do
|
|
216
|
+
Doorkeeper.configure do
|
|
217
|
+
token_reuse_limit 90
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
expect(subject.token_reuse_limit).to eq(90)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it 'sets the value to 100 if invalid value is being set' do
|
|
224
|
+
expect(Rails.logger).to receive(:warn).with(/will be set to default 100/)
|
|
225
|
+
|
|
226
|
+
Doorkeeper.configure do
|
|
227
|
+
reuse_access_token
|
|
228
|
+
token_reuse_limit 110
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
expect(subject.token_reuse_limit).to eq(100)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
194
235
|
describe 'enforce_configured_scopes' do
|
|
195
236
|
it 'is false by default' do
|
|
196
237
|
expect(subject.enforce_configured_scopes?).to eq(false)
|
|
@@ -441,6 +482,22 @@ describe Doorkeeper, 'configuration' do
|
|
|
441
482
|
end
|
|
442
483
|
end
|
|
443
484
|
|
|
485
|
+
describe 'default_generator_method' do
|
|
486
|
+
it "is :urlsafe_base64 by default" do
|
|
487
|
+
expect(Doorkeeper.configuration.default_generator_method)
|
|
488
|
+
.to eq(:urlsafe_base64)
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
it 'can change the value' do
|
|
492
|
+
Doorkeeper.configure do
|
|
493
|
+
orm DOORKEEPER_ORM
|
|
494
|
+
default_generator_method :hex
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
expect(subject.default_generator_method).to eq(:hex)
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
444
501
|
describe 'base_controller' do
|
|
445
502
|
context 'default' do
|
|
446
503
|
it { expect(Doorkeeper.configuration.base_controller).to eq('ActionController::Base') }
|
|
@@ -525,4 +582,115 @@ describe Doorkeeper, 'configuration' do
|
|
|
525
582
|
expect(subject.handle_auth_errors).to eq(:raise)
|
|
526
583
|
end
|
|
527
584
|
end
|
|
585
|
+
|
|
586
|
+
describe 'token_secret_strategy' do
|
|
587
|
+
it 'is plain by default' do
|
|
588
|
+
expect(subject.token_secret_strategy).to eq(Doorkeeper::SecretStoring::Plain)
|
|
589
|
+
expect(subject.token_secret_fallback_strategy).to eq(nil)
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
context 'when provided' do
|
|
593
|
+
before do
|
|
594
|
+
Doorkeeper.configure do
|
|
595
|
+
hash_token_secrets
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
it 'will enable hashing for applications' do
|
|
600
|
+
expect(subject.token_secret_strategy).to eq(Doorkeeper::SecretStoring::Sha256Hash)
|
|
601
|
+
expect(subject.token_secret_fallback_strategy).to eq(nil)
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
context 'when manually provided with invalid constant' do
|
|
606
|
+
it 'raises an exception' do
|
|
607
|
+
expect {
|
|
608
|
+
Doorkeeper.configure do
|
|
609
|
+
hash_token_secrets using: 'does not exist'
|
|
610
|
+
end
|
|
611
|
+
}.to raise_error(NameError)
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
context 'when manually provided with invalid option' do
|
|
616
|
+
it 'raises an exception' do
|
|
617
|
+
expect do
|
|
618
|
+
Doorkeeper.configure do
|
|
619
|
+
hash_token_secrets using: 'Doorkeeper::SecretStoring::BCrypt'
|
|
620
|
+
end
|
|
621
|
+
end.to raise_error(ArgumentError,
|
|
622
|
+
/can only be used for storing application secrets/)
|
|
623
|
+
end
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
context 'when provided with fallback' do
|
|
627
|
+
before do
|
|
628
|
+
Doorkeeper.configure do
|
|
629
|
+
hash_token_secrets fallback: :plain
|
|
630
|
+
end
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
it 'will enable hashing for applications' do
|
|
634
|
+
expect(subject.token_secret_strategy).to eq(Doorkeeper::SecretStoring::Sha256Hash)
|
|
635
|
+
expect(subject.token_secret_fallback_strategy).to eq(Doorkeeper::SecretStoring::Plain)
|
|
636
|
+
end
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
describe 'hash_token_secrets together with reuse_access_token' do
|
|
641
|
+
it 'will disable reuse_access_token' do
|
|
642
|
+
expect(Rails.logger).to receive(:warn).with(/reuse_access_token will be disabled/)
|
|
643
|
+
|
|
644
|
+
Doorkeeper.configure do
|
|
645
|
+
reuse_access_token
|
|
646
|
+
hash_token_secrets
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
expect(subject.reuse_access_token).to eq(false)
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
describe 'application_secret_strategy' do
|
|
655
|
+
it 'is plain by default' do
|
|
656
|
+
expect(subject.application_secret_strategy).to eq(Doorkeeper::SecretStoring::Plain)
|
|
657
|
+
expect(subject.application_secret_fallback_strategy).to eq(nil)
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
context 'when provided' do
|
|
661
|
+
before do
|
|
662
|
+
Doorkeeper.configure do
|
|
663
|
+
hash_application_secrets
|
|
664
|
+
end
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
it 'will enable hashing for applications' do
|
|
668
|
+
expect(subject.application_secret_strategy).to eq(Doorkeeper::SecretStoring::Sha256Hash)
|
|
669
|
+
expect(subject.application_secret_fallback_strategy).to eq(nil)
|
|
670
|
+
end
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
context 'when manually provided with invalid constant' do
|
|
674
|
+
it 'raises an exception' do
|
|
675
|
+
expect {
|
|
676
|
+
Doorkeeper.configure do
|
|
677
|
+
hash_application_secrets using: 'does not exist'
|
|
678
|
+
end
|
|
679
|
+
}.to raise_error(NameError)
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
context 'when provided with fallback' do
|
|
684
|
+
before do
|
|
685
|
+
Doorkeeper.configure do
|
|
686
|
+
hash_application_secrets fallback: :plain
|
|
687
|
+
end
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
it 'will enable hashing for applications' do
|
|
691
|
+
expect(subject.application_secret_strategy).to eq(Doorkeeper::SecretStoring::Sha256Hash)
|
|
692
|
+
expect(subject.application_secret_fallback_strategy).to eq(Doorkeeper::SecretStoring::Plain)
|
|
693
|
+
end
|
|
694
|
+
end
|
|
695
|
+
end
|
|
528
696
|
end
|
|
@@ -44,4 +44,16 @@ describe 'Expirable' do
|
|
|
44
44
|
expect(subject.expires_in_seconds).to be_nil
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
|
+
|
|
48
|
+
describe :expires_at do
|
|
49
|
+
it 'should return the expiration time of the token' do
|
|
50
|
+
allow(subject).to receive(:expires_in).and_return(2.minutes)
|
|
51
|
+
expect(subject.expires_at).to be_a(Time)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'should return nil when expires_in is nil' do
|
|
55
|
+
allow(subject).to receive(:expires_in).and_return(nil)
|
|
56
|
+
expect(subject.expires_at).to be_nil
|
|
57
|
+
end
|
|
58
|
+
end
|
|
47
59
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'Reusable' do
|
|
6
|
+
subject do
|
|
7
|
+
Class.new do
|
|
8
|
+
include Doorkeeper::Models::Reusable
|
|
9
|
+
end.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe :reusable? do
|
|
13
|
+
it 'is reusable if its expires_in is nil' do
|
|
14
|
+
allow(subject).to receive(:expired?).and_return(false)
|
|
15
|
+
allow(subject).to receive(:expires_in).and_return(nil)
|
|
16
|
+
expect(subject).to be_reusable
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'is reusable if its expiry has crossed reusable limit' do
|
|
20
|
+
allow(subject).to receive(:expired?).and_return(false)
|
|
21
|
+
allow(Doorkeeper.configuration).to receive(:token_reuse_limit).and_return(90)
|
|
22
|
+
allow(subject).to receive(:expires_in).and_return(100.seconds)
|
|
23
|
+
allow(subject).to receive(:expires_in_seconds).and_return(20.seconds)
|
|
24
|
+
expect(subject).to be_reusable
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'is not reusable if its expiry has crossed reusable limit' do
|
|
28
|
+
allow(subject).to receive(:expired?).and_return(false)
|
|
29
|
+
allow(Doorkeeper.configuration).to receive(:token_reuse_limit).and_return(90)
|
|
30
|
+
allow(subject).to receive(:expires_in).and_return(100.seconds)
|
|
31
|
+
allow(subject).to receive(:expires_in_seconds).and_return(5.seconds)
|
|
32
|
+
expect(subject).not_to be_reusable
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'is not reusable if it is already expired' do
|
|
36
|
+
allow(subject).to receive(:expired?).and_return(true)
|
|
37
|
+
expect(subject).not_to be_reusable
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe 'Doorkeeper::Models::Scopes' do
|
|
4
4
|
subject do
|
|
5
|
-
Class.new(
|
|
5
|
+
Class.new(Struct.new(:scopes)) do
|
|
6
6
|
include Doorkeeper::Models::Scopes
|
|
7
7
|
end.new
|
|
8
8
|
end
|
|
@@ -21,6 +21,18 @@ describe 'Doorkeeper::Models::Scopes' do
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
describe :scopes= do
|
|
25
|
+
it 'accepts String' do
|
|
26
|
+
subject.scopes = 'private admin'
|
|
27
|
+
expect(subject.scopes_string).to eq('private admin')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'accepts Array' do
|
|
31
|
+
subject.scopes = %w[private admin]
|
|
32
|
+
expect(subject.scopes_string).to eq('private admin')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
24
36
|
describe :scopes_string do
|
|
25
37
|
it 'is a `Scopes` class' do
|
|
26
38
|
expect(subject.scopes_string).to eq('public admin')
|