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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/workflows/spec.yml +32 -0
  4. data/CHANGELOG.md +25 -0
  5. data/README.rdoc +1 -26
  6. data/VERSION +1 -1
  7. data/lib/rack/oauth2/access_token/authenticator.rb +1 -10
  8. data/lib/rack/oauth2/access_token/bearer.rb +1 -1
  9. data/lib/rack/oauth2/access_token/mtls.rb +2 -2
  10. data/lib/rack/oauth2/access_token.rb +4 -6
  11. data/lib/rack/oauth2/client.rb +97 -41
  12. data/lib/rack/oauth2/server/abstract/error.rb +2 -1
  13. data/lib/rack/oauth2/server/extension/pkce.rb +1 -1
  14. data/lib/rack/oauth2/server/rails/response_ext.rb +5 -5
  15. data/lib/rack/oauth2/server/resource/error.rb +4 -4
  16. data/lib/rack/oauth2/server/resource.rb +0 -1
  17. data/lib/rack/oauth2/server/token/error.rb +3 -1
  18. data/lib/rack/oauth2/server/token.rb +16 -5
  19. data/lib/rack/oauth2/urn.rb +3 -3
  20. data/lib/rack/oauth2/util.rb +6 -2
  21. data/lib/rack/oauth2.rb +11 -10
  22. data/rack-oauth2.gemspec +7 -5
  23. data/spec/helpers/webmock_helper.rb +8 -2
  24. data/spec/rack/oauth2/access_token/authenticator_spec.rb +2 -22
  25. data/spec/rack/oauth2/access_token/bearer_spec.rb +2 -2
  26. data/spec/rack/oauth2/access_token_spec.rb +0 -17
  27. data/spec/rack/oauth2/client_spec.rb +173 -75
  28. data/spec/rack/oauth2/oauth2_spec.rb +0 -43
  29. data/spec/rack/oauth2/server/authorize/error_spec.rb +6 -6
  30. data/spec/rack/oauth2/server/resource/bearer/error_spec.rb +2 -2
  31. data/spec/rack/oauth2/server/resource/bearer_spec.rb +9 -9
  32. data/spec/rack/oauth2/server/resource/error_spec.rb +21 -21
  33. data/spec/rack/oauth2/server/token/authorization_code_spec.rb +2 -2
  34. data/spec/rack/oauth2/server/token/client_credentials_spec.rb +32 -2
  35. data/spec/rack/oauth2/server/token/error_spec.rb +8 -8
  36. data/spec/rack/oauth2/server/token_spec.rb +72 -3
  37. data/spec/rack/oauth2/util_spec.rb +8 -3
  38. metadata +47 -51
  39. data/.travis.yml +0 -7
  40. data/lib/rack/oauth2/access_token/legacy.rb +0 -19
  41. data/lib/rack/oauth2/access_token/mac/sha256_hex_verifier.rb +0 -17
  42. data/lib/rack/oauth2/access_token/mac/signature.rb +0 -34
  43. data/lib/rack/oauth2/access_token/mac/verifier.rb +0 -44
  44. data/lib/rack/oauth2/access_token/mac.rb +0 -103
  45. data/lib/rack/oauth2/debugger/request_filter.rb +0 -30
  46. data/lib/rack/oauth2/debugger.rb +0 -3
  47. data/lib/rack/oauth2/server/resource/mac/error.rb +0 -24
  48. data/lib/rack/oauth2/server/resource/mac.rb +0 -36
  49. data/spec/mock_response/tokens/legacy.json +0 -5
  50. data/spec/mock_response/tokens/legacy.txt +0 -1
  51. data/spec/mock_response/tokens/legacy_without_expires_in.txt +0 -1
  52. data/spec/mock_response/tokens/mac.json +0 -8
  53. data/spec/rack/oauth2/access_token/legacy_spec.rb +0 -23
  54. data/spec/rack/oauth2/access_token/mac/sha256_hex_verifier_spec.rb +0 -28
  55. data/spec/rack/oauth2/access_token/mac/signature_spec.rb +0 -59
  56. data/spec/rack/oauth2/access_token/mac/verifier_spec.rb +0 -25
  57. data/spec/rack/oauth2/access_token/mac_spec.rb +0 -141
  58. data/spec/rack/oauth2/debugger/request_filter_spec.rb +0 -33
  59. data/spec/rack/oauth2/server/resource/mac/error_spec.rb +0 -52
  60. data/spec/rack/oauth2/server/resource/mac_spec.rb +0 -119
  61. /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 and MAC token type are supported.}
6
- s.summary = %q{OAuth 2.0 Server & Client Library - Both Bearer and MAC token type are supported}
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 = 'http://github.com/nov/rack-oauth2'
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', '< 2.1'
17
- s.add_runtime_dependency 'httpclient'
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.try(:[], :params) || {}
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
- response[:body] = File.new(File.join(File.dirname(__FILE__), '../mock_response', response_file))
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) { HTTP::Message.new_request(:get, URI.parse(resource_endpoint)) }
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.filter_request(request)
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) { HTTPClient.new.send(:create_request, :post, URI.parse(resource_endpoint), {}, {hello: "world"}, {}) }
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.header).to receive(:[]=).with('Authorization', 'Bearer access_token')
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: 'client_id',
7
- secret: 'client_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.json',
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.json',
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.json',
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.new('prime256v1').generate_key,
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.json',
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.json',
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.json',
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.json',
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.json',
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.json',
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.json'
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.json'
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 mac token is given' do
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/mac.json'
364
+ 'tokens/unknown'
308
365
  )
309
366
  end
310
- it { should be_instance_of Rack::OAuth2::AccessToken::MAC }
311
- its(:token_type) { should == :mac }
312
- its(:access_token) { should == 'access_token' }
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 no-type token is given (JSON)' do
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
- 'tokens/legacy.json'
377
+ 'errors/invalid_request',
378
+ status: 400
324
379
  )
325
380
  end
326
- it { should be_instance_of Rack::OAuth2::AccessToken::Legacy }
327
- its(:token_type) { should == :legacy }
328
- its(:access_token) { should == 'access_token' }
329
- its(:refresh_token) { should == 'refresh_token' }
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
- context 'when token_type is forced' do
386
+ context 'when no body given' do
387
+ context 'when error given' do
333
388
  before do
334
- client.force_token_type! :bearer
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
- context 'when no-type token is given (key-value)' do
342
- before do
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/token',
346
- 'tokens/legacy.txt'
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
- end
349
- it { should be_instance_of Rack::OAuth2::AccessToken::Legacy }
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 unknown-type token is given' do
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/token',
372
- 'tokens/unknown.json'
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
- expect { client.access_token! }.to raise_error(StandardError, 'Unknown Token Type')
443
+ client.revoke!(access_token: 'access_token').should == :success
377
444
  end
378
445
  end
379
446
 
380
- context 'when error response is given' do
447
+ context 'when refresh_token given' do
381
448
  before do
382
449
  mock_response(
383
450
  :post,
384
- 'https://server.example.com/oauth2/token',
385
- 'errors/invalid_request.json',
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 { client.access_token! }.to raise_error Rack::OAuth2::Client::Error
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 body given' do
395
- context 'when error given' do
396
- before do
397
- mock_response(
398
- :post,
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, header, response = error.finish
26
+ state, headers, response = error.finish
27
27
  state.should == 302
28
- header["Location"].should == "#{redirect_uri}?error=invalid_request"
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, header, response = error.finish
35
+ state, headers, response = error.finish
36
36
  state.should == 302
37
- header["Location"].should == "#{redirect_uri}#error=invalid_request"
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, header, response = error.finish
44
+ state, headers, response = error.finish
45
45
  state.should == 302
46
- header["Location"].should == redirect_uri
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, header, response = error.finish
16
- header['WWW-Authenticate'].should include 'Bearer'
15
+ status, headers, response = error.finish
16
+ headers['WWW-Authenticate'].should include 'Bearer'
17
17
  end
18
18
  end
19
19
  end