rack-oauth2 1.12.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +3 -0
- data/.github/workflows/spec.yml +32 -0
- data/CHANGELOG.md +25 -0
- data/README.rdoc +1 -26
- data/VERSION +1 -1
- data/lib/rack/oauth2/access_token/authenticator.rb +1 -10
- data/lib/rack/oauth2/access_token/bearer.rb +1 -1
- data/lib/rack/oauth2/access_token/mtls.rb +2 -2
- data/lib/rack/oauth2/access_token.rb +4 -6
- data/lib/rack/oauth2/client.rb +97 -41
- data/lib/rack/oauth2/server/abstract/error.rb +2 -1
- data/lib/rack/oauth2/server/extension/pkce.rb +1 -1
- data/lib/rack/oauth2/server/rails/response_ext.rb +5 -5
- data/lib/rack/oauth2/server/resource/error.rb +4 -4
- data/lib/rack/oauth2/server/resource.rb +0 -1
- data/lib/rack/oauth2/server/token/error.rb +3 -1
- data/lib/rack/oauth2/server/token.rb +16 -5
- data/lib/rack/oauth2/urn.rb +3 -3
- data/lib/rack/oauth2/util.rb +6 -2
- data/lib/rack/oauth2.rb +11 -10
- data/rack-oauth2.gemspec +7 -5
- data/spec/helpers/webmock_helper.rb +8 -2
- data/spec/rack/oauth2/access_token/authenticator_spec.rb +2 -22
- data/spec/rack/oauth2/access_token/bearer_spec.rb +2 -2
- data/spec/rack/oauth2/access_token_spec.rb +0 -17
- data/spec/rack/oauth2/client_spec.rb +173 -75
- data/spec/rack/oauth2/oauth2_spec.rb +0 -43
- data/spec/rack/oauth2/server/authorize/error_spec.rb +6 -6
- data/spec/rack/oauth2/server/resource/bearer/error_spec.rb +2 -2
- data/spec/rack/oauth2/server/resource/bearer_spec.rb +9 -9
- data/spec/rack/oauth2/server/resource/error_spec.rb +21 -21
- data/spec/rack/oauth2/server/token/authorization_code_spec.rb +2 -2
- data/spec/rack/oauth2/server/token/client_credentials_spec.rb +32 -2
- data/spec/rack/oauth2/server/token/error_spec.rb +8 -8
- data/spec/rack/oauth2/server/token_spec.rb +72 -3
- data/spec/rack/oauth2/util_spec.rb +8 -3
- metadata +47 -51
- data/.travis.yml +0 -7
- data/lib/rack/oauth2/access_token/legacy.rb +0 -19
- data/lib/rack/oauth2/access_token/mac/sha256_hex_verifier.rb +0 -17
- data/lib/rack/oauth2/access_token/mac/signature.rb +0 -34
- data/lib/rack/oauth2/access_token/mac/verifier.rb +0 -44
- data/lib/rack/oauth2/access_token/mac.rb +0 -103
- data/lib/rack/oauth2/debugger/request_filter.rb +0 -30
- data/lib/rack/oauth2/debugger.rb +0 -3
- data/lib/rack/oauth2/server/resource/mac/error.rb +0 -24
- data/lib/rack/oauth2/server/resource/mac.rb +0 -36
- data/spec/mock_response/tokens/legacy.json +0 -5
- data/spec/mock_response/tokens/legacy.txt +0 -1
- data/spec/mock_response/tokens/legacy_without_expires_in.txt +0 -1
- data/spec/mock_response/tokens/mac.json +0 -8
- data/spec/rack/oauth2/access_token/legacy_spec.rb +0 -23
- data/spec/rack/oauth2/access_token/mac/sha256_hex_verifier_spec.rb +0 -28
- data/spec/rack/oauth2/access_token/mac/signature_spec.rb +0 -59
- data/spec/rack/oauth2/access_token/mac/verifier_spec.rb +0 -25
- data/spec/rack/oauth2/access_token/mac_spec.rb +0 -141
- data/spec/rack/oauth2/debugger/request_filter_spec.rb +0 -33
- data/spec/rack/oauth2/server/resource/mac/error_spec.rb +0 -52
- data/spec/rack/oauth2/server/resource/mac_spec.rb +0 -119
- /data/spec/mock_response/{blank → blank.txt} +0 -0
data/rack-oauth2.gemspec
CHANGED
@@ -2,19 +2,20 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.name = 'rack-oauth2'
|
3
3
|
s.version = File.read('VERSION')
|
4
4
|
s.authors = ['nov matake']
|
5
|
-
s.description = %q{OAuth 2.0 Server & Client Library. Both Bearer
|
6
|
-
s.summary = %q{OAuth 2.0 Server & Client Library - Both Bearer
|
5
|
+
s.description = %q{OAuth 2.0 Server & Client Library. Both Bearer token type are supported.}
|
6
|
+
s.summary = %q{OAuth 2.0 Server & Client Library - Both Bearer token type are supported}
|
7
7
|
s.email = 'nov@matake.jp'
|
8
8
|
s.extra_rdoc_files = ['LICENSE', 'README.rdoc']
|
9
9
|
s.rdoc_options = ['--charset=UTF-8']
|
10
|
-
s.homepage = '
|
10
|
+
s.homepage = 'https://github.com/nov/rack-oauth2'
|
11
11
|
s.license = 'MIT'
|
12
12
|
s.require_paths = ['lib']
|
13
13
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
14
14
|
s.files = `git ls-files`.split("\n")
|
15
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
-
s.add_runtime_dependency 'rack', '
|
17
|
-
s.add_runtime_dependency '
|
16
|
+
s.add_runtime_dependency 'rack', '>= 2.1.0'
|
17
|
+
s.add_runtime_dependency 'faraday', '~> 2.0'
|
18
|
+
s.add_runtime_dependency 'faraday-follow_redirects'
|
18
19
|
s.add_runtime_dependency 'activesupport'
|
19
20
|
s.add_runtime_dependency 'attr_required'
|
20
21
|
s.add_runtime_dependency 'json-jwt', '>= 1.11.0'
|
@@ -23,4 +24,5 @@ Gem::Specification.new do |s|
|
|
23
24
|
s.add_development_dependency 'rspec'
|
24
25
|
s.add_development_dependency 'rspec-its'
|
25
26
|
s.add_development_dependency 'webmock'
|
27
|
+
s.add_development_dependency 'rexml'
|
26
28
|
end
|
@@ -13,7 +13,7 @@ module WebMockHelper
|
|
13
13
|
|
14
14
|
def request_for(method, options = {})
|
15
15
|
request = {}
|
16
|
-
params = options
|
16
|
+
params = options&.[](:params) || {}
|
17
17
|
case method
|
18
18
|
when :post, :put, :delete
|
19
19
|
request[:body] = params
|
@@ -28,7 +28,13 @@ module WebMockHelper
|
|
28
28
|
|
29
29
|
def response_for(response_file, options = {})
|
30
30
|
response = {}
|
31
|
-
|
31
|
+
format = options[:format] || :json
|
32
|
+
if format == :json
|
33
|
+
response[:headers] = {
|
34
|
+
'Content-Type': 'application/json'
|
35
|
+
}
|
36
|
+
end
|
37
|
+
response[:body] = File.new(File.join(File.dirname(__FILE__), '../mock_response', "#{response_file}.#{format}"))
|
32
38
|
if options[:status]
|
33
39
|
response[:status] = options[:status]
|
34
40
|
end
|
@@ -2,25 +2,16 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Rack::OAuth2::AccessToken::Authenticator do
|
4
4
|
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
|
5
|
-
let(:request) {
|
5
|
+
let(:request) { Faraday::Request.new(:get, URI.parse(resource_endpoint)) }
|
6
6
|
let(:authenticator) { Rack::OAuth2::AccessToken::Authenticator.new(token) }
|
7
7
|
|
8
8
|
shared_examples_for :authenticator do
|
9
9
|
it 'should let the token authenticate the request' do
|
10
10
|
expect(token).to receive(:authenticate).with(request)
|
11
|
-
authenticator.
|
11
|
+
authenticator.authenticate(request)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
context 'when Legacy token is given' do
|
16
|
-
let(:token) do
|
17
|
-
Rack::OAuth2::AccessToken::Legacy.new(
|
18
|
-
access_token: 'access_token'
|
19
|
-
)
|
20
|
-
end
|
21
|
-
it_behaves_like :authenticator
|
22
|
-
end
|
23
|
-
|
24
15
|
context 'when Bearer token is given' do
|
25
16
|
let(:token) do
|
26
17
|
Rack::OAuth2::AccessToken::Bearer.new(
|
@@ -29,15 +20,4 @@ describe Rack::OAuth2::AccessToken::Authenticator do
|
|
29
20
|
end
|
30
21
|
it_behaves_like :authenticator
|
31
22
|
end
|
32
|
-
|
33
|
-
context 'when MAC token is given' do
|
34
|
-
let(:token) do
|
35
|
-
Rack::OAuth2::AccessToken::MAC.new(
|
36
|
-
access_token: 'access_token',
|
37
|
-
mac_key: 'secret',
|
38
|
-
mac_algorithm: 'hmac-sha-256'
|
39
|
-
)
|
40
|
-
end
|
41
|
-
it_behaves_like :authenticator
|
42
|
-
end
|
43
23
|
end
|
@@ -7,11 +7,11 @@ describe Rack::OAuth2::AccessToken::Bearer do
|
|
7
7
|
)
|
8
8
|
end
|
9
9
|
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
|
10
|
-
let(:request) {
|
10
|
+
let(:request) { Faraday::Request.new(:post, URI.parse(resource_endpoint), '', {hello: "world"}, {}) }
|
11
11
|
|
12
12
|
describe '.authenticate' do
|
13
13
|
it 'should set Authorization header' do
|
14
|
-
expect(request.
|
14
|
+
expect(request.headers).to receive(:[]=).with('Authorization', 'Bearer access_token')
|
15
15
|
token.authenticate(request)
|
16
16
|
end
|
17
17
|
end
|
@@ -49,23 +49,6 @@ describe Rack::OAuth2::AccessToken do
|
|
49
49
|
|
50
50
|
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
|
51
51
|
[:get, :delete, :post, :put].each do |method|
|
52
|
-
describe method do
|
53
|
-
it 'should delegate to HTTPClient with Authenticator filter' do
|
54
|
-
expect(token.httpclient).to receive(method).with(resource_endpoint)
|
55
|
-
token.httpclient.request_filter.last.should be_a Rack::OAuth2::AccessToken::Authenticator
|
56
|
-
token.send method, resource_endpoint
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
context 'in debug mode' do
|
61
|
-
it do
|
62
|
-
Rack::OAuth2.debug do
|
63
|
-
token.httpclient.request_filter[-2].should be_a Rack::OAuth2::AccessToken::Authenticator
|
64
|
-
token.httpclient.request_filter.last.should be_a Rack::OAuth2::Debugger::RequestFilter
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
52
|
context 'when extension params given' do
|
70
53
|
subject do
|
71
54
|
Rack::OAuth2::AccessToken::Bearer.new(
|
@@ -1,12 +1,15 @@
|
|
1
1
|
require 'spec_helper.rb'
|
2
2
|
|
3
3
|
describe Rack::OAuth2::Client do
|
4
|
+
let(:client_id) { 'client_id' }
|
5
|
+
let(:client_secret) { 'client_secret' }
|
4
6
|
let :client do
|
5
7
|
Rack::OAuth2::Client.new(
|
6
|
-
identifier:
|
7
|
-
secret:
|
8
|
+
identifier: client_id,
|
9
|
+
secret: client_secret,
|
8
10
|
host: 'server.example.com',
|
9
|
-
redirect_uri: 'https://client.example.com/callback'
|
11
|
+
redirect_uri: 'https://client.example.com/callback',
|
12
|
+
revocation_endpoint: '/oauth2/revoke'
|
10
13
|
)
|
11
14
|
end
|
12
15
|
subject { client }
|
@@ -15,6 +18,7 @@ describe Rack::OAuth2::Client do
|
|
15
18
|
its(:secret) { should == 'client_secret' }
|
16
19
|
its(:authorization_endpoint) { should == '/oauth2/authorize' }
|
17
20
|
its(:token_endpoint) { should == '/oauth2/token' }
|
21
|
+
its(:revocation_endpoint) { should == '/oauth2/revoke' }
|
18
22
|
|
19
23
|
context 'when identifier is missing' do
|
20
24
|
it do
|
@@ -89,7 +93,7 @@ describe Rack::OAuth2::Client do
|
|
89
93
|
mock_response(
|
90
94
|
:post,
|
91
95
|
'https://server.example.com/oauth2/token',
|
92
|
-
'tokens/bearer
|
96
|
+
'tokens/bearer',
|
93
97
|
request_header: {
|
94
98
|
'Authorization' => 'Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ='
|
95
99
|
}
|
@@ -97,13 +101,49 @@ describe Rack::OAuth2::Client do
|
|
97
101
|
client.access_token!
|
98
102
|
end
|
99
103
|
|
104
|
+
context 'when Basic auth method is used' do
|
105
|
+
context 'when client_id is a url' do
|
106
|
+
let(:client_id) { 'https://client.example.com'}
|
107
|
+
|
108
|
+
it 'should be encoded in "application/x-www-form-urlencoded"' do
|
109
|
+
mock_response(
|
110
|
+
:post,
|
111
|
+
'https://server.example.com/oauth2/token',
|
112
|
+
'tokens/bearer',
|
113
|
+
request_header: {
|
114
|
+
'Authorization' => 'Basic aHR0cHMlM0ElMkYlMkZjbGllbnQuZXhhbXBsZS5jb206Y2xpZW50X3NlY3JldA=='
|
115
|
+
}
|
116
|
+
)
|
117
|
+
client.access_token!
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'when basic_without_www_form_urlencode method is used' do
|
123
|
+
context 'when client_id is a url' do
|
124
|
+
let(:client_id) { 'https://client.example.com'}
|
125
|
+
|
126
|
+
it 'should be encoded in "application/x-www-form-urlencoded"' do
|
127
|
+
mock_response(
|
128
|
+
:post,
|
129
|
+
'https://server.example.com/oauth2/token',
|
130
|
+
'tokens/bearer',
|
131
|
+
request_header: {
|
132
|
+
'Authorization' => 'Basic aHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb206Y2xpZW50X3NlY3JldA=='
|
133
|
+
}
|
134
|
+
)
|
135
|
+
client.access_token! :basic_without_www_form_urlencode
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
100
140
|
context 'when jwt_bearer auth method specified' do
|
101
141
|
context 'when client_secret is given' do
|
102
142
|
it 'should be JWT bearer client assertion w/ auto-generated HS256-signed JWT assertion' do
|
103
143
|
mock_response(
|
104
144
|
:post,
|
105
145
|
'https://server.example.com/oauth2/token',
|
106
|
-
'tokens/bearer
|
146
|
+
'tokens/bearer',
|
107
147
|
params: {
|
108
148
|
client_assertion: /^eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9\..+/, # NOTE: HS256
|
109
149
|
client_assertion_type: Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER,
|
@@ -131,7 +171,7 @@ describe Rack::OAuth2::Client do
|
|
131
171
|
mock_response(
|
132
172
|
:post,
|
133
173
|
'https://server.example.com/oauth2/token',
|
134
|
-
'tokens/bearer
|
174
|
+
'tokens/bearer',
|
135
175
|
params: {
|
136
176
|
client_assertion: /^eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9\..+/, # NOTE: RS256
|
137
177
|
client_assertion_type: Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER,
|
@@ -148,7 +188,7 @@ describe Rack::OAuth2::Client do
|
|
148
188
|
let :client do
|
149
189
|
Rack::OAuth2::Client.new(
|
150
190
|
identifier: 'client_id',
|
151
|
-
private_key: OpenSSL::PKey::EC.
|
191
|
+
private_key: OpenSSL::PKey::EC.generate('prime256v1'),
|
152
192
|
host: 'server.example.com',
|
153
193
|
redirect_uri: 'https://client.example.com/callback'
|
154
194
|
)
|
@@ -158,7 +198,7 @@ describe Rack::OAuth2::Client do
|
|
158
198
|
mock_response(
|
159
199
|
:post,
|
160
200
|
'https://server.example.com/oauth2/token',
|
161
|
-
'tokens/bearer
|
201
|
+
'tokens/bearer',
|
162
202
|
params: {
|
163
203
|
client_assertion: /^eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9\..+/, # NOTE: ES256
|
164
204
|
client_assertion_type: Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER,
|
@@ -185,7 +225,7 @@ describe Rack::OAuth2::Client do
|
|
185
225
|
mock_response(
|
186
226
|
:post,
|
187
227
|
'https://server.example.com/oauth2/token',
|
188
|
-
'tokens/bearer
|
228
|
+
'tokens/bearer',
|
189
229
|
params: {
|
190
230
|
client_assertion: 'any.jwt.assertion',
|
191
231
|
client_assertion_type: Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER,
|
@@ -204,7 +244,7 @@ describe Rack::OAuth2::Client do
|
|
204
244
|
mock_response(
|
205
245
|
:post,
|
206
246
|
'https://server.example.com/oauth2/token',
|
207
|
-
'tokens/bearer
|
247
|
+
'tokens/bearer',
|
208
248
|
params: {
|
209
249
|
client_id: 'client_id',
|
210
250
|
client_secret: 'client_secret',
|
@@ -222,7 +262,7 @@ describe Rack::OAuth2::Client do
|
|
222
262
|
mock_response(
|
223
263
|
:post,
|
224
264
|
'https://server.example.com/oauth2/token',
|
225
|
-
'tokens/bearer
|
265
|
+
'tokens/bearer',
|
226
266
|
params: {
|
227
267
|
client_id: 'client_id',
|
228
268
|
client_secret: 'client_secret',
|
@@ -242,7 +282,7 @@ describe Rack::OAuth2::Client do
|
|
242
282
|
mock_response(
|
243
283
|
:post,
|
244
284
|
'https://server.example.com/oauth2/token',
|
245
|
-
'tokens/bearer
|
285
|
+
'tokens/bearer',
|
246
286
|
params: {
|
247
287
|
grant_type: 'client_credentials',
|
248
288
|
scope: 'a b'
|
@@ -258,7 +298,7 @@ describe Rack::OAuth2::Client do
|
|
258
298
|
mock_response(
|
259
299
|
:post,
|
260
300
|
'https://server.example.com/oauth2/token',
|
261
|
-
'tokens/bearer
|
301
|
+
'tokens/bearer',
|
262
302
|
params: {
|
263
303
|
grant_type: 'client_credentials',
|
264
304
|
resource: 'something'
|
@@ -269,13 +309,30 @@ describe Rack::OAuth2::Client do
|
|
269
309
|
end
|
270
310
|
end
|
271
311
|
|
312
|
+
context 'local_http_config handling' do
|
313
|
+
it do
|
314
|
+
mock_response(
|
315
|
+
:post,
|
316
|
+
'https://server.example.com/oauth2/token',
|
317
|
+
'tokens/bearer',
|
318
|
+
request_header: {
|
319
|
+
'Authorization' => 'Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=',
|
320
|
+
'X-Foo' => 'bar'
|
321
|
+
}
|
322
|
+
)
|
323
|
+
client.access_token! do |request|
|
324
|
+
request.headers['X-Foo'] = 'bar'
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
272
329
|
context 'when bearer token is given' do
|
273
330
|
before do
|
274
331
|
client.authorization_code = 'code'
|
275
332
|
mock_response(
|
276
333
|
:post,
|
277
334
|
'https://server.example.com/oauth2/token',
|
278
|
-
'tokens/bearer
|
335
|
+
'tokens/bearer'
|
279
336
|
)
|
280
337
|
end
|
281
338
|
it { should be_instance_of Rack::OAuth2::AccessToken::Bearer }
|
@@ -290,7 +347,7 @@ describe Rack::OAuth2::Client do
|
|
290
347
|
mock_response(
|
291
348
|
:post,
|
292
349
|
'https://server.example.com/oauth2/token',
|
293
|
-
'tokens/_Bearer
|
350
|
+
'tokens/_Bearer'
|
294
351
|
)
|
295
352
|
end
|
296
353
|
it { should be_instance_of Rack::OAuth2::AccessToken::Bearer }
|
@@ -298,112 +355,146 @@ describe Rack::OAuth2::Client do
|
|
298
355
|
end
|
299
356
|
end
|
300
357
|
|
301
|
-
context 'when
|
358
|
+
context 'when unknown-type token is given' do
|
302
359
|
before do
|
303
360
|
client.authorization_code = 'code'
|
304
361
|
mock_response(
|
305
362
|
:post,
|
306
363
|
'https://server.example.com/oauth2/token',
|
307
|
-
'tokens/
|
364
|
+
'tokens/unknown'
|
308
365
|
)
|
309
366
|
end
|
310
|
-
it
|
311
|
-
|
312
|
-
|
313
|
-
its(:refresh_token) { should == 'refresh_token' }
|
314
|
-
its(:expires_in) { should == 3600 }
|
367
|
+
it do
|
368
|
+
expect { client.access_token! }.to raise_error(StandardError, 'Unknown Token Type')
|
369
|
+
end
|
315
370
|
end
|
316
371
|
|
317
|
-
context 'when
|
372
|
+
context 'when error response is given' do
|
318
373
|
before do
|
319
|
-
client.authorization_code = 'code'
|
320
374
|
mock_response(
|
321
375
|
:post,
|
322
376
|
'https://server.example.com/oauth2/token',
|
323
|
-
'
|
377
|
+
'errors/invalid_request',
|
378
|
+
status: 400
|
324
379
|
)
|
325
380
|
end
|
326
|
-
it
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
its(:expires_in) { should == 3600 }
|
381
|
+
it do
|
382
|
+
expect { client.access_token! }.to raise_error Rack::OAuth2::Client::Error
|
383
|
+
end
|
384
|
+
end
|
331
385
|
|
332
|
-
|
386
|
+
context 'when no body given' do
|
387
|
+
context 'when error given' do
|
333
388
|
before do
|
334
|
-
|
389
|
+
mock_response(
|
390
|
+
:post,
|
391
|
+
'https://server.example.com/oauth2/token',
|
392
|
+
'blank',
|
393
|
+
format: 'txt',
|
394
|
+
status: 400
|
395
|
+
)
|
396
|
+
end
|
397
|
+
it do
|
398
|
+
expect { client.access_token! }.to raise_error Rack::OAuth2::Client::Error
|
335
399
|
end
|
336
|
-
it { should be_instance_of Rack::OAuth2::AccessToken::Bearer }
|
337
|
-
its(:token_type) { should == :bearer }
|
338
400
|
end
|
339
401
|
end
|
402
|
+
end
|
340
403
|
|
341
|
-
|
342
|
-
|
404
|
+
describe '#revoke!' do
|
405
|
+
context 'local_http_config handling' do
|
406
|
+
it do
|
343
407
|
mock_response(
|
344
408
|
:post,
|
345
|
-
'https://server.example.com/oauth2/
|
346
|
-
'
|
409
|
+
'https://server.example.com/oauth2/revoke',
|
410
|
+
'blank',
|
411
|
+
format: 'txt',
|
412
|
+
status: 200,
|
413
|
+
body: {
|
414
|
+
token: 'access_token',
|
415
|
+
token_type_hint: 'access_token'
|
416
|
+
},
|
417
|
+
request_header: {
|
418
|
+
'Authorization' => 'Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=',
|
419
|
+
'X-Foo' => 'bar'
|
420
|
+
}
|
347
421
|
)
|
348
|
-
|
349
|
-
|
350
|
-
its(:token_type) { should == :legacy }
|
351
|
-
its(:access_token) { should == 'access_token' }
|
352
|
-
its(:expires_in) { should == 3600 }
|
353
|
-
|
354
|
-
context 'when expires_in is not given' do
|
355
|
-
before do
|
356
|
-
mock_response(
|
357
|
-
:post,
|
358
|
-
'https://server.example.com/oauth2/token',
|
359
|
-
'tokens/legacy_without_expires_in.txt'
|
360
|
-
)
|
422
|
+
client.revoke!(access_token: 'access_token') do |request|
|
423
|
+
request.headers['X-Foo'] = 'bar'
|
361
424
|
end
|
362
|
-
its(:expires_in) { should be_nil }
|
363
425
|
end
|
364
426
|
end
|
365
427
|
|
366
|
-
context 'when
|
428
|
+
context 'when access_token given' do
|
367
429
|
before do
|
368
|
-
client.authorization_code = 'code'
|
369
430
|
mock_response(
|
370
431
|
:post,
|
371
|
-
'https://server.example.com/oauth2/
|
372
|
-
'
|
432
|
+
'https://server.example.com/oauth2/revoke',
|
433
|
+
'blank',
|
434
|
+
format: 'txt',
|
435
|
+
status: 200,
|
436
|
+
body: {
|
437
|
+
token: 'access_token',
|
438
|
+
token_type_hint: 'access_token'
|
439
|
+
}
|
373
440
|
)
|
374
441
|
end
|
375
442
|
it do
|
376
|
-
|
443
|
+
client.revoke!(access_token: 'access_token').should == :success
|
377
444
|
end
|
378
445
|
end
|
379
446
|
|
380
|
-
context 'when
|
447
|
+
context 'when refresh_token given' do
|
381
448
|
before do
|
382
449
|
mock_response(
|
383
450
|
:post,
|
384
|
-
'https://server.example.com/oauth2/
|
385
|
-
'
|
451
|
+
'https://server.example.com/oauth2/revoke',
|
452
|
+
'blank',
|
453
|
+
format: 'txt',
|
454
|
+
status: 200,
|
455
|
+
body: {
|
456
|
+
token: 'refresh_token',
|
457
|
+
token_type_hint: 'refresh_token'
|
458
|
+
}
|
459
|
+
)
|
460
|
+
end
|
461
|
+
|
462
|
+
context 'as argument' do
|
463
|
+
it do
|
464
|
+
client.revoke!(refresh_token: 'refresh_token').should == :success
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
context 'as grant' do
|
469
|
+
it do
|
470
|
+
client.refresh_token = 'refresh_token'
|
471
|
+
client.revoke!
|
472
|
+
end
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
context 'when error response given' do
|
477
|
+
before do
|
478
|
+
mock_response(
|
479
|
+
:post,
|
480
|
+
'https://server.example.com/oauth2/revoke',
|
481
|
+
'errors/invalid_request',
|
386
482
|
status: 400
|
387
483
|
)
|
388
484
|
end
|
485
|
+
|
389
486
|
it do
|
390
|
-
expect
|
487
|
+
expect do
|
488
|
+
client.revoke! access_token: 'access_token'
|
489
|
+
end.to raise_error Rack::OAuth2::Client::Error
|
391
490
|
end
|
392
491
|
end
|
393
492
|
|
394
|
-
context 'when no
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
'https://server.example.com/oauth2/token',
|
400
|
-
'blank',
|
401
|
-
status: 400
|
402
|
-
)
|
403
|
-
end
|
404
|
-
it do
|
405
|
-
expect { client.access_token! }.to raise_error Rack::OAuth2::Client::Error
|
406
|
-
end
|
493
|
+
context 'when no token given' do
|
494
|
+
it do
|
495
|
+
expect do
|
496
|
+
client.revoke!
|
497
|
+
end.to raise_error ArgumentError
|
407
498
|
end
|
408
499
|
end
|
409
500
|
end
|
@@ -413,7 +504,8 @@ describe Rack::OAuth2::Client do
|
|
413
504
|
Rack::OAuth2::Client.new(
|
414
505
|
identifier: 'client_id',
|
415
506
|
secret: 'client_secret',
|
416
|
-
redirect_uri: 'https://client.example.com/callback'
|
507
|
+
redirect_uri: 'https://client.example.com/callback',
|
508
|
+
revocation_endpoint: '/oauth2/revoke'
|
417
509
|
)
|
418
510
|
end
|
419
511
|
|
@@ -428,5 +520,11 @@ describe Rack::OAuth2::Client do
|
|
428
520
|
expect { client.access_token! }.to raise_error 'No Host Info'
|
429
521
|
end
|
430
522
|
end
|
523
|
+
|
524
|
+
describe '#revoke!' do
|
525
|
+
it do
|
526
|
+
expect { client.revoke! access_token: 'access_token' }.to raise_error 'No Host Info'
|
527
|
+
end
|
528
|
+
end
|
431
529
|
end
|
432
530
|
end
|
@@ -28,47 +28,4 @@ describe Rack::OAuth2 do
|
|
28
28
|
Rack::OAuth2.debugging?.should == true
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
32
|
-
describe '.http_config' do
|
33
|
-
context 'when request_filter added' do
|
34
|
-
context 'when "debug!" is called' do
|
35
|
-
after { Rack::OAuth2.reset_http_config! }
|
36
|
-
|
37
|
-
it 'should put Debugger::RequestFilter at last' do
|
38
|
-
Rack::OAuth2.debug!
|
39
|
-
Rack::OAuth2.http_config do |config|
|
40
|
-
config.request_filter << Proc.new {}
|
41
|
-
end
|
42
|
-
Rack::OAuth2.http_client.request_filter.last.should be_instance_of Rack::OAuth2::Debugger::RequestFilter
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'should reset_http_config' do
|
46
|
-
Rack::OAuth2.debug!
|
47
|
-
Rack::OAuth2.http_config do |config|
|
48
|
-
config.request_filter << Proc.new {}
|
49
|
-
end
|
50
|
-
size = Rack::OAuth2.http_client.request_filter.size
|
51
|
-
Rack::OAuth2.reset_http_config!
|
52
|
-
Rack::OAuth2.http_client.request_filter.size.should == size - 1
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe ".http_client" do
|
60
|
-
context "when local_http_config is used" do
|
61
|
-
it "should correctly set request_filter" do
|
62
|
-
clnt1 = Rack::OAuth2.http_client
|
63
|
-
clnt2 = Rack::OAuth2.http_client("my client") do |config|
|
64
|
-
config.request_filter << Proc.new {}
|
65
|
-
end
|
66
|
-
clnt3 = Rack::OAuth2.http_client
|
67
|
-
|
68
|
-
clnt1.request_filter.size.should == clnt3.request_filter.size
|
69
|
-
clnt1.request_filter.size.should == clnt2.request_filter.size - 1
|
70
|
-
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
31
|
end
|
@@ -23,27 +23,27 @@ describe Rack::OAuth2::Server::Authorize::BadRequest do
|
|
23
23
|
context 'when protocol_params_location = :query' do
|
24
24
|
before { error.protocol_params_location = :query }
|
25
25
|
it 'should redirect with error in query' do
|
26
|
-
state,
|
26
|
+
state, headers, response = error.finish
|
27
27
|
state.should == 302
|
28
|
-
|
28
|
+
headers["Location"].should == "#{redirect_uri}?error=invalid_request"
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'when protocol_params_location = :fragment' do
|
33
33
|
before { error.protocol_params_location = :fragment }
|
34
34
|
it 'should redirect with error in fragment' do
|
35
|
-
state,
|
35
|
+
state, headers, response = error.finish
|
36
36
|
state.should == 302
|
37
|
-
|
37
|
+
headers["Location"].should == "#{redirect_uri}#error=invalid_request"
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
context 'otherwise' do
|
42
42
|
before { error.protocol_params_location = :other }
|
43
43
|
it 'should redirect without error' do
|
44
|
-
state,
|
44
|
+
state, headers, response = error.finish
|
45
45
|
state.should == 302
|
46
|
-
|
46
|
+
headers["Location"].should == redirect_uri
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
@@ -12,8 +12,8 @@ describe Rack::OAuth2::Server::Resource::Bearer::Unauthorized do
|
|
12
12
|
|
13
13
|
describe '#finish' do
|
14
14
|
it 'should use Bearer scheme' do
|
15
|
-
status,
|
16
|
-
|
15
|
+
status, headers, response = error.finish
|
16
|
+
headers['WWW-Authenticate'].should include 'Bearer'
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|