rack-oauth2 1.12.0 → 2.2.0
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 +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
|