rack-oauth2 1.19.0 → 1.21.2
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/.travis.yml +1 -1
- data/VERSION +1 -1
- data/lib/rack/oauth2/client.rb +75 -24
- data/rack-oauth2.gemspec +2 -1
- data/spec/rack/oauth2/client_spec.rb +84 -2
- metadata +19 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bedb933d3946aef05d7ca583bd18b46941aebdf7fc0f8640be2f5909f9be4e9c
|
|
4
|
+
data.tar.gz: 8740a613173e5edd0c98d79d1079b933d3eaee89b56369ae109d10841d7b94d8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 465ffccc2e5e41e396949947904f359a6d67d5637e6b0056a8bbca10f3b6755b14682fcad8092dddba7eabca72b66e1f66691b20a3351c79a7b1269abb478c07
|
|
7
|
+
data.tar.gz: c0b6d79ad4c019fa58034d446acaf7ee2d6ec5b9cf77e5b8548f924cbbc544e34d6c09d6a2433e9ed5dbca7915b27280602ce8a62dda12722a9b28a3c6c07bb8
|
data/.github/FUNDING.yml
ADDED
data/.travis.yml
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.21.2
|
data/lib/rack/oauth2/client.rb
CHANGED
|
@@ -3,7 +3,7 @@ module Rack
|
|
|
3
3
|
class Client
|
|
4
4
|
include AttrRequired, AttrOptional
|
|
5
5
|
attr_required :identifier
|
|
6
|
-
attr_optional :secret, :private_key, :certificate, :redirect_uri, :scheme, :host, :port, :authorization_endpoint, :token_endpoint
|
|
6
|
+
attr_optional :secret, :private_key, :certificate, :redirect_uri, :scheme, :host, :port, :authorization_endpoint, :token_endpoint, :revocation_endpoint
|
|
7
7
|
|
|
8
8
|
def initialize(attributes = {})
|
|
9
9
|
(required_attributes + optional_attributes).each do |key|
|
|
@@ -69,7 +69,65 @@ module Rack
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def access_token!(*args)
|
|
72
|
-
headers, params =
|
|
72
|
+
headers, params, http_client, options = authenticated_context_from(*args)
|
|
73
|
+
params[:scope] = Array(options.delete(:scope)).join(' ') if options[:scope].present?
|
|
74
|
+
params.merge! @grant.as_json
|
|
75
|
+
params.merge! options
|
|
76
|
+
handle_response do
|
|
77
|
+
http_client.post(
|
|
78
|
+
absolute_uri_for(token_endpoint),
|
|
79
|
+
Util.compact_hash(params),
|
|
80
|
+
headers
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def revoke!(*args)
|
|
86
|
+
headers, params, http_client, options = authenticated_context_from(*args)
|
|
87
|
+
|
|
88
|
+
params.merge! case
|
|
89
|
+
when access_token = options.delete(:access_token)
|
|
90
|
+
{
|
|
91
|
+
token: access_token,
|
|
92
|
+
token_type_hint: :access_token
|
|
93
|
+
}
|
|
94
|
+
when refresh_token = options.delete(:refresh_token)
|
|
95
|
+
{
|
|
96
|
+
token: refresh_token,
|
|
97
|
+
token_type_hint: :refresh_token
|
|
98
|
+
}
|
|
99
|
+
when @grant.is_a?(Grant::RefreshToken)
|
|
100
|
+
{
|
|
101
|
+
token: @grant.refresh_token,
|
|
102
|
+
token_type_hint: :refresh_token
|
|
103
|
+
}
|
|
104
|
+
when options[:token].blank?
|
|
105
|
+
raise ArgumentError, 'One of "token", "access_token" and "refresh_token" is required'
|
|
106
|
+
end
|
|
107
|
+
params.merge! options
|
|
108
|
+
|
|
109
|
+
handle_revocation_response do
|
|
110
|
+
http_client.post(
|
|
111
|
+
absolute_uri_for(revocation_endpoint),
|
|
112
|
+
Util.compact_hash(params),
|
|
113
|
+
headers
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
def absolute_uri_for(endpoint)
|
|
121
|
+
_endpoint_ = Util.parse_uri endpoint
|
|
122
|
+
_endpoint_.scheme ||= self.scheme || 'https'
|
|
123
|
+
_endpoint_.host ||= self.host
|
|
124
|
+
_endpoint_.port ||= self.port
|
|
125
|
+
raise 'No Host Info' unless _endpoint_.host
|
|
126
|
+
_endpoint_.to_s
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def authenticated_context_from(*args)
|
|
130
|
+
headers, params = {}, {}
|
|
73
131
|
http_client = Rack::OAuth2.http_client
|
|
74
132
|
|
|
75
133
|
# NOTE:
|
|
@@ -78,9 +136,6 @@ module Rack
|
|
|
78
136
|
options = args.extract_options!
|
|
79
137
|
client_auth_method = args.first || options.delete(:client_auth_method).try(:to_sym) || :basic
|
|
80
138
|
|
|
81
|
-
params[:scope] = Array(options.delete(:scope)).join(' ') if options[:scope].present?
|
|
82
|
-
params.merge! options
|
|
83
|
-
|
|
84
139
|
case client_auth_method
|
|
85
140
|
when :basic
|
|
86
141
|
cred = Base64.strict_encode64 [
|
|
@@ -100,9 +155,11 @@ module Rack
|
|
|
100
155
|
client_assertion_type: URN::ClientAssertionType::JWT_BEARER
|
|
101
156
|
)
|
|
102
157
|
# NOTE: optionally auto-generate client_assertion.
|
|
103
|
-
if
|
|
158
|
+
params[:client_assertion] = if options[:client_assertion].present?
|
|
159
|
+
options.delete(:client_assertion)
|
|
160
|
+
else
|
|
104
161
|
require 'json/jwt'
|
|
105
|
-
|
|
162
|
+
JSON::JWT.new(
|
|
106
163
|
iss: identifier,
|
|
107
164
|
sub: identifier,
|
|
108
165
|
aud: absolute_uri_for(token_endpoint),
|
|
@@ -127,24 +184,8 @@ module Rack
|
|
|
127
184
|
client_secret: secret
|
|
128
185
|
)
|
|
129
186
|
end
|
|
130
|
-
handle_response do
|
|
131
|
-
http_client.post(
|
|
132
|
-
absolute_uri_for(token_endpoint),
|
|
133
|
-
Util.compact_hash(params),
|
|
134
|
-
headers
|
|
135
|
-
)
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
private
|
|
140
187
|
|
|
141
|
-
|
|
142
|
-
_endpoint_ = Util.parse_uri endpoint
|
|
143
|
-
_endpoint_.scheme ||= self.scheme || 'https'
|
|
144
|
-
_endpoint_.host ||= self.host
|
|
145
|
-
_endpoint_.port ||= self.port
|
|
146
|
-
raise 'No Host Info' unless _endpoint_.host
|
|
147
|
-
_endpoint_.to_s
|
|
188
|
+
[headers, params, http_client, options]
|
|
148
189
|
end
|
|
149
190
|
|
|
150
191
|
def handle_response
|
|
@@ -157,6 +198,16 @@ module Rack
|
|
|
157
198
|
end
|
|
158
199
|
end
|
|
159
200
|
|
|
201
|
+
def handle_revocation_response
|
|
202
|
+
response = yield
|
|
203
|
+
case response.status
|
|
204
|
+
when 200..201
|
|
205
|
+
:success
|
|
206
|
+
else
|
|
207
|
+
handle_error_response response
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
160
211
|
def handle_success_response(response)
|
|
161
212
|
token_hash = JSON.parse(response.body).with_indifferent_access
|
|
162
213
|
case (@forced_token_type || token_hash[:token_type]).try(:downcase)
|
data/rack-oauth2.gemspec
CHANGED
|
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
|
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) }
|
|
@@ -23,4 +23,5 @@ Gem::Specification.new do |s|
|
|
|
23
23
|
s.add_development_dependency 'rspec'
|
|
24
24
|
s.add_development_dependency 'rspec-its'
|
|
25
25
|
s.add_development_dependency 'webmock'
|
|
26
|
+
s.add_development_dependency 'rexml'
|
|
26
27
|
end
|
|
@@ -8,7 +8,8 @@ describe Rack::OAuth2::Client do
|
|
|
8
8
|
identifier: client_id,
|
|
9
9
|
secret: client_secret,
|
|
10
10
|
host: 'server.example.com',
|
|
11
|
-
redirect_uri: 'https://client.example.com/callback'
|
|
11
|
+
redirect_uri: 'https://client.example.com/callback',
|
|
12
|
+
revocation_endpoint: '/oauth2/revoke'
|
|
12
13
|
)
|
|
13
14
|
end
|
|
14
15
|
subject { client }
|
|
@@ -17,6 +18,7 @@ describe Rack::OAuth2::Client do
|
|
|
17
18
|
its(:secret) { should == 'client_secret' }
|
|
18
19
|
its(:authorization_endpoint) { should == '/oauth2/authorize' }
|
|
19
20
|
its(:token_endpoint) { should == '/oauth2/token' }
|
|
21
|
+
its(:revocation_endpoint) { should == '/oauth2/revoke' }
|
|
20
22
|
|
|
21
23
|
context 'when identifier is missing' do
|
|
22
24
|
it do
|
|
@@ -446,12 +448,86 @@ describe Rack::OAuth2::Client do
|
|
|
446
448
|
end
|
|
447
449
|
end
|
|
448
450
|
|
|
451
|
+
describe '#revoke!' do
|
|
452
|
+
context 'when access_token given' do
|
|
453
|
+
before do
|
|
454
|
+
mock_response(
|
|
455
|
+
:post,
|
|
456
|
+
'https://server.example.com/oauth2/revoke',
|
|
457
|
+
'blank',
|
|
458
|
+
status: 200,
|
|
459
|
+
body: {
|
|
460
|
+
token: 'access_token',
|
|
461
|
+
token_type_hint: 'access_token'
|
|
462
|
+
}
|
|
463
|
+
)
|
|
464
|
+
end
|
|
465
|
+
it do
|
|
466
|
+
client.revoke!(access_token: 'access_token').should == :success
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
context 'when refresh_token given' do
|
|
471
|
+
before do
|
|
472
|
+
mock_response(
|
|
473
|
+
:post,
|
|
474
|
+
'https://server.example.com/oauth2/revoke',
|
|
475
|
+
'blank',
|
|
476
|
+
status: 200,
|
|
477
|
+
body: {
|
|
478
|
+
token: 'refresh_token',
|
|
479
|
+
token_type_hint: 'refresh_token'
|
|
480
|
+
}
|
|
481
|
+
)
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
context 'as argument' do
|
|
485
|
+
it do
|
|
486
|
+
client.revoke!(refresh_token: 'refresh_token').should == :success
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
context 'as grant' do
|
|
491
|
+
it do
|
|
492
|
+
client.refresh_token = 'refresh_token'
|
|
493
|
+
client.revoke!
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
context 'when error response given' do
|
|
499
|
+
before do
|
|
500
|
+
mock_response(
|
|
501
|
+
:post,
|
|
502
|
+
'https://server.example.com/oauth2/revoke',
|
|
503
|
+
'errors/invalid_request.json',
|
|
504
|
+
status: 400
|
|
505
|
+
)
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
it do
|
|
509
|
+
expect do
|
|
510
|
+
client.revoke! access_token: 'access_token'
|
|
511
|
+
end.to raise_error Rack::OAuth2::Client::Error
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
context 'when no token given' do
|
|
516
|
+
it do
|
|
517
|
+
expect do
|
|
518
|
+
client.revoke!
|
|
519
|
+
end.to raise_error ArgumentError
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
|
|
449
524
|
context 'when no host info' do
|
|
450
525
|
let :client do
|
|
451
526
|
Rack::OAuth2::Client.new(
|
|
452
527
|
identifier: 'client_id',
|
|
453
528
|
secret: 'client_secret',
|
|
454
|
-
redirect_uri: 'https://client.example.com/callback'
|
|
529
|
+
redirect_uri: 'https://client.example.com/callback',
|
|
530
|
+
revocation_endpoint: '/oauth2/revoke'
|
|
455
531
|
)
|
|
456
532
|
end
|
|
457
533
|
|
|
@@ -466,5 +542,11 @@ describe Rack::OAuth2::Client do
|
|
|
466
542
|
expect { client.access_token! }.to raise_error 'No Host Info'
|
|
467
543
|
end
|
|
468
544
|
end
|
|
545
|
+
|
|
546
|
+
describe '#revoke!' do
|
|
547
|
+
it do
|
|
548
|
+
expect { client.revoke! access_token: 'access_token' }.to raise_error 'No Host Info'
|
|
549
|
+
end
|
|
550
|
+
end
|
|
469
551
|
end
|
|
470
552
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rack-oauth2
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.21.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nov matake
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-07-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -150,6 +150,20 @@ dependencies:
|
|
|
150
150
|
- - ">="
|
|
151
151
|
- !ruby/object:Gem::Version
|
|
152
152
|
version: '0'
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
154
|
+
name: rexml
|
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
|
156
|
+
requirements:
|
|
157
|
+
- - ">="
|
|
158
|
+
- !ruby/object:Gem::Version
|
|
159
|
+
version: '0'
|
|
160
|
+
type: :development
|
|
161
|
+
prerelease: false
|
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
+
requirements:
|
|
164
|
+
- - ">="
|
|
165
|
+
- !ruby/object:Gem::Version
|
|
166
|
+
version: '0'
|
|
153
167
|
description: OAuth 2.0 Server & Client Library. Both Bearer and MAC token type are
|
|
154
168
|
supported.
|
|
155
169
|
email: nov@matake.jp
|
|
@@ -160,6 +174,7 @@ extra_rdoc_files:
|
|
|
160
174
|
- README.rdoc
|
|
161
175
|
files:
|
|
162
176
|
- ".document"
|
|
177
|
+
- ".github/FUNDING.yml"
|
|
163
178
|
- ".gitignore"
|
|
164
179
|
- ".rspec"
|
|
165
180
|
- ".travis.yml"
|
|
@@ -281,7 +296,7 @@ files:
|
|
|
281
296
|
- spec/rack/oauth2/server/token_spec.rb
|
|
282
297
|
- spec/rack/oauth2/util_spec.rb
|
|
283
298
|
- spec/spec_helper.rb
|
|
284
|
-
homepage:
|
|
299
|
+
homepage: https://github.com/nov/rack-oauth2
|
|
285
300
|
licenses:
|
|
286
301
|
- MIT
|
|
287
302
|
metadata: {}
|
|
@@ -301,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
301
316
|
- !ruby/object:Gem::Version
|
|
302
317
|
version: '0'
|
|
303
318
|
requirements: []
|
|
304
|
-
rubygems_version: 3.1.
|
|
319
|
+
rubygems_version: 3.1.6
|
|
305
320
|
signing_key:
|
|
306
321
|
specification_version: 4
|
|
307
322
|
summary: OAuth 2.0 Server & Client Library - Both Bearer and MAC token type are supported
|