rack-oauth2 0.7.0 → 0.8.0.alpha
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.
- data/Gemfile.lock +9 -9
- data/VERSION +1 -1
- data/lib/rack/oauth2.rb +1 -1
- data/lib/rack/oauth2/access_token.rb +5 -17
- data/lib/rack/oauth2/access_token/authenticator.rb +24 -0
- data/lib/rack/oauth2/access_token/bearer.rb +2 -3
- data/lib/rack/oauth2/access_token/legacy.rb +2 -3
- data/lib/rack/oauth2/access_token/mac.rb +19 -45
- data/lib/rack/oauth2/client.rb +17 -4
- data/rack-oauth2.gemspec +2 -2
- data/spec/helpers/webmock_helper.rb +42 -0
- data/spec/{fake_response → mock_response}/errors/invalid_request.json +0 -0
- data/spec/{fake_response → mock_response}/resources/fake.txt +0 -0
- data/spec/{fake_response → mock_response}/tokens/bearer.json +0 -0
- data/spec/{fake_response → mock_response}/tokens/legacy.json +0 -0
- data/spec/{fake_response → mock_response}/tokens/legacy.txt +0 -0
- data/spec/{fake_response → mock_response}/tokens/legacy_without_expires_in.txt +0 -0
- data/spec/{fake_response → mock_response}/tokens/mac.json +0 -0
- data/spec/{fake_response → mock_response}/tokens/unknown.json +0 -0
- data/spec/rack/oauth2/access_token/authenticator_spec.rb +43 -0
- data/spec/rack/oauth2/access_token/bearer_spec.rb +5 -30
- data/spec/rack/oauth2/access_token/legacy_spec.rb +8 -33
- data/spec/rack/oauth2/access_token/mac_spec.rb +21 -65
- data/spec/rack/oauth2/access_token_spec.rb +13 -1
- data/spec/rack/oauth2/client_spec.rb +7 -7
- data/spec/spec_helper.rb +2 -15
- metadata +28 -23
data/Gemfile.lock
CHANGED
|
@@ -1,31 +1,28 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
rack-oauth2 (0.
|
|
4
|
+
rack-oauth2 (0.8.0.alpha)
|
|
5
5
|
activesupport (>= 2.3)
|
|
6
6
|
attr_required (>= 0.0.3)
|
|
7
|
+
httpclient (>= 2.2.0.2)
|
|
7
8
|
i18n
|
|
8
9
|
json (>= 1.4.3)
|
|
9
10
|
rack (>= 1.1)
|
|
10
|
-
restclient_with_cert
|
|
11
11
|
|
|
12
12
|
GEM
|
|
13
13
|
remote: http://rubygems.org/
|
|
14
14
|
specs:
|
|
15
15
|
activesupport (3.0.7)
|
|
16
|
+
addressable (2.2.6)
|
|
16
17
|
attr_required (0.0.3)
|
|
18
|
+
crack (0.1.8)
|
|
17
19
|
diff-lcs (1.1.2)
|
|
18
|
-
|
|
20
|
+
httpclient (2.2.0.2)
|
|
19
21
|
i18n (0.5.0)
|
|
20
22
|
json (1.5.1)
|
|
21
|
-
mime-types (1.16)
|
|
22
23
|
rack (1.2.2)
|
|
23
24
|
rake (0.8.7)
|
|
24
25
|
rcov (0.9.9)
|
|
25
|
-
rest-client (1.6.1)
|
|
26
|
-
mime-types (>= 1.16)
|
|
27
|
-
restclient_with_cert (0.0.7)
|
|
28
|
-
rest-client (>= 1.6)
|
|
29
26
|
rspec (2.5.0)
|
|
30
27
|
rspec-core (~> 2.5.0)
|
|
31
28
|
rspec-expectations (~> 2.5.0)
|
|
@@ -34,13 +31,16 @@ GEM
|
|
|
34
31
|
rspec-expectations (2.5.0)
|
|
35
32
|
diff-lcs (~> 1.1.2)
|
|
36
33
|
rspec-mocks (2.5.0)
|
|
34
|
+
webmock (1.6.4)
|
|
35
|
+
addressable (> 2.2.5, ~> 2.2)
|
|
36
|
+
crack (>= 0.1.7)
|
|
37
37
|
|
|
38
38
|
PLATFORMS
|
|
39
39
|
ruby
|
|
40
40
|
|
|
41
41
|
DEPENDENCIES
|
|
42
|
-
fakeweb (>= 1.3)
|
|
43
42
|
rack-oauth2!
|
|
44
43
|
rake (>= 0.8)
|
|
45
44
|
rcov (>= 0.9)
|
|
46
45
|
rspec (<= 2.5, >= 2)
|
|
46
|
+
webmock (>= 1.6.2)
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.8.0.alpha
|
data/lib/rack/oauth2.rb
CHANGED
|
@@ -2,14 +2,17 @@ module Rack
|
|
|
2
2
|
module OAuth2
|
|
3
3
|
class AccessToken
|
|
4
4
|
include AttrRequired, AttrOptional
|
|
5
|
-
attr_required :access_token, :token_type
|
|
5
|
+
attr_required :access_token, :token_type, :client
|
|
6
6
|
attr_optional :refresh_token, :expires_in, :scope
|
|
7
|
+
delegate :get, :post, :put, :delete, :to => :client
|
|
7
8
|
|
|
8
9
|
def initialize(attributes = {})
|
|
9
10
|
(required_attributes + optional_attributes).each do |key|
|
|
10
11
|
self.send :"#{key}=", attributes[key]
|
|
11
12
|
end
|
|
12
13
|
@token_type = self.class.to_s.split('::').last.underscore.to_sym
|
|
14
|
+
@client = HTTPClient.new
|
|
15
|
+
@client.request_filter << Authenticator.new(self)
|
|
13
16
|
attr_missing!
|
|
14
17
|
end
|
|
15
18
|
|
|
@@ -22,26 +25,11 @@ module Rack
|
|
|
22
25
|
:scope => Array(scope).join(' ')
|
|
23
26
|
}
|
|
24
27
|
end
|
|
25
|
-
|
|
26
|
-
def get(url, headers = {}, &block)
|
|
27
|
-
RestClient.get url, authenticate(headers), &block
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def post(url, payload, headers = {}, &block)
|
|
31
|
-
RestClient.post url, payload, authenticate(headers), &block
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def put(url, payload, headers = {}, &block)
|
|
35
|
-
RestClient.put url, payload, authenticate(headers), &block
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def delete(url, headers = {}, &block)
|
|
39
|
-
RestClient.delete url, authenticate(headers), &block
|
|
40
|
-
end
|
|
41
28
|
end
|
|
42
29
|
end
|
|
43
30
|
end
|
|
44
31
|
|
|
32
|
+
require 'rack/oauth2/access_token/authenticator'
|
|
45
33
|
require 'rack/oauth2/access_token/bearer'
|
|
46
34
|
require 'rack/oauth2/access_token/mac'
|
|
47
35
|
require 'rack/oauth2/access_token/legacy'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Rack
|
|
2
|
+
module OAuth2
|
|
3
|
+
class AccessToken
|
|
4
|
+
class Authenticator
|
|
5
|
+
def initialize(token)
|
|
6
|
+
@token = token
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Callback called in HTTPClient (before sending a request)
|
|
10
|
+
# request:: HTTP::Message
|
|
11
|
+
def filter_request(request)
|
|
12
|
+
@token.authenticate(request)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Callback called in HTTPClient (after received a response)
|
|
16
|
+
# response:: HTTP::Message
|
|
17
|
+
# request:: HTTP::Message
|
|
18
|
+
def filter_response(response, request)
|
|
19
|
+
# nothing to do
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -2,9 +2,8 @@ module Rack
|
|
|
2
2
|
module OAuth2
|
|
3
3
|
class AccessToken
|
|
4
4
|
class Bearer < AccessToken
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
headers.merge(:AUTHORIZATION => "Bearer #{access_token}")
|
|
5
|
+
def authenticate(request)
|
|
6
|
+
request.header["Authorization"] = "Bearer #{access_token}"
|
|
8
7
|
end
|
|
9
8
|
end
|
|
10
9
|
end
|
|
@@ -11,9 +11,8 @@ module Rack
|
|
|
11
11
|
self.access_token
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
headers.merge(:AUTHORIZATION => "OAuth2 #{access_token}")
|
|
14
|
+
def authenticate(request)
|
|
15
|
+
request.header["Authorization"] = "OAuth2 #{access_token}"
|
|
17
16
|
end
|
|
18
17
|
end
|
|
19
18
|
end
|
|
@@ -20,13 +20,12 @@ module Rack
|
|
|
20
20
|
|
|
21
21
|
def verify!(request)
|
|
22
22
|
if request.body_hash.present?
|
|
23
|
-
|
|
23
|
+
BodyHash.new(
|
|
24
24
|
:raw_body => request.body.read,
|
|
25
25
|
:algorithm => self.mac_algorithm
|
|
26
|
-
)
|
|
27
|
-
_body_hash_.verify!(request.body_hash)
|
|
26
|
+
).verify!(request.body_hash)
|
|
28
27
|
end
|
|
29
|
-
|
|
28
|
+
Signature.new(
|
|
30
29
|
:secret => self.mac_key,
|
|
31
30
|
:algorithm => self.mac_algorithm,
|
|
32
31
|
:nonce => request.nonce,
|
|
@@ -36,60 +35,35 @@ module Rack
|
|
|
36
35
|
:port => request.port,
|
|
37
36
|
:body_hash => request.body_hash,
|
|
38
37
|
:ext => request.ext
|
|
39
|
-
)
|
|
40
|
-
_signature_.verify!(request.signature)
|
|
38
|
+
).verify!(request.signature)
|
|
41
39
|
rescue Verifier::VerificationFailed => e
|
|
42
40
|
request.invalid_token! e.message
|
|
43
41
|
end
|
|
44
42
|
|
|
45
|
-
def
|
|
46
|
-
_headers_ = authenticate(:get, url, headers)
|
|
47
|
-
RestClient.get url, _headers_, &block
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def post(url, payload, headers = {}, &block)
|
|
51
|
-
_headers_ = authenticate(:post, url, headers, payload)
|
|
52
|
-
RestClient.post url, payload, _headers_, &block
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def put(url, payload, headers = {}, &block)
|
|
56
|
-
_headers_ = authenticate(:put, url, headers, payload)
|
|
57
|
-
RestClient.put url, payload, _headers_, &block
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def delete(url, headers = {}, &block)
|
|
61
|
-
_headers_ = authenticate(:delete, url, headers)
|
|
62
|
-
RestClient.delete url, _headers_, &block
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
private
|
|
66
|
-
|
|
67
|
-
def authenticate(method, url, headers = {}, payload = {})
|
|
68
|
-
_url_ = URI.parse(url)
|
|
43
|
+
def authenticate(request)
|
|
69
44
|
@nonce = generate_nonce
|
|
70
|
-
if
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
:raw_body => raw_body,
|
|
45
|
+
if request.contenttype == 'application/x-www-form-urlencoded'
|
|
46
|
+
@body_hash = BodyHash.new(
|
|
47
|
+
:raw_body => request.body,
|
|
74
48
|
:algorithm => self.mac_algorithm
|
|
75
|
-
)
|
|
76
|
-
@body_hash = _body_hash_.calculate
|
|
49
|
+
).calculate
|
|
77
50
|
end
|
|
78
|
-
|
|
51
|
+
@signature = Signature.new(
|
|
79
52
|
:secret => self.mac_key,
|
|
80
53
|
:algorithm => self.mac_algorithm,
|
|
81
54
|
:nonce => self.nonce,
|
|
82
|
-
:method =>
|
|
83
|
-
:request_uri =>
|
|
84
|
-
:host =>
|
|
85
|
-
:port =>
|
|
55
|
+
:method => request.header.request_method,
|
|
56
|
+
:request_uri => request.header.create_query_uri,
|
|
57
|
+
:host => request.header.request_uri.host,
|
|
58
|
+
:port => request.header.request_uri.port,
|
|
86
59
|
:body_hash => self.body_hash,
|
|
87
60
|
:ext => self.ext
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
headers.merge(:AUTHORIZATION => authorization_header)
|
|
61
|
+
).calculate
|
|
62
|
+
request.header['Authorization'] = authorization_header
|
|
91
63
|
end
|
|
92
64
|
|
|
65
|
+
private
|
|
66
|
+
|
|
93
67
|
def authorization_header
|
|
94
68
|
header = "MAC"
|
|
95
69
|
header << " id=\"#{access_token}\","
|
|
@@ -102,7 +76,7 @@ module Rack
|
|
|
102
76
|
def generate_nonce
|
|
103
77
|
[
|
|
104
78
|
(Time.now.utc - @issued_at).to_i,
|
|
105
|
-
ActiveSupport::SecureRandom.
|
|
79
|
+
ActiveSupport::SecureRandom.hex
|
|
106
80
|
].join(':')
|
|
107
81
|
end
|
|
108
82
|
end
|
data/lib/rack/oauth2/client.rb
CHANGED
|
@@ -51,7 +51,7 @@ module Rack
|
|
|
51
51
|
:client_secret => self.secret
|
|
52
52
|
)
|
|
53
53
|
handle_response do
|
|
54
|
-
|
|
54
|
+
HTTPClient.new.post absolute_uri_for(token_endpoint), Util.compact_hash(params)
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
57
|
|
|
@@ -67,6 +67,15 @@ module Rack
|
|
|
67
67
|
|
|
68
68
|
def handle_response
|
|
69
69
|
response = yield
|
|
70
|
+
case response.status
|
|
71
|
+
when 200..201
|
|
72
|
+
handle_success_response response
|
|
73
|
+
else
|
|
74
|
+
handle_error_response response
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def handle_success_response(response)
|
|
70
79
|
token_hash = JSON.parse(response.body).with_indifferent_access
|
|
71
80
|
case token_hash[:token_type]
|
|
72
81
|
when 'bearer'
|
|
@@ -81,9 +90,13 @@ module Rack
|
|
|
81
90
|
rescue JSON::ParserError
|
|
82
91
|
# NOTE: Facebook support (They don't use JSON as token response)
|
|
83
92
|
AccessToken::Legacy.new Rack::Utils.parse_nested_query(response.body).with_indifferent_access
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def handle_error_response(response)
|
|
96
|
+
error = JSON.parse(response.body).with_indifferent_access
|
|
97
|
+
raise Error.new(response.status, error)
|
|
98
|
+
rescue JSON::ParserError
|
|
99
|
+
raise Error.new(response.status, :error => 'Unknown', :error_description => resonse.body)
|
|
87
100
|
end
|
|
88
101
|
end
|
|
89
102
|
end
|
data/rack-oauth2.gemspec
CHANGED
|
@@ -15,12 +15,12 @@ Gem::Specification.new do |s|
|
|
|
15
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
16
16
|
s.add_runtime_dependency "rack", ">= 1.1"
|
|
17
17
|
s.add_runtime_dependency "json", ">= 1.4.3"
|
|
18
|
-
s.add_runtime_dependency "
|
|
18
|
+
s.add_runtime_dependency "httpclient", ">= 2.2.0.2"
|
|
19
19
|
s.add_runtime_dependency "activesupport", ">= 2.3"
|
|
20
20
|
s.add_runtime_dependency "i18n"
|
|
21
21
|
s.add_runtime_dependency "attr_required", ">= 0.0.3"
|
|
22
22
|
s.add_development_dependency "rake", ">= 0.8"
|
|
23
23
|
s.add_development_dependency "rcov", ">= 0.9"
|
|
24
24
|
s.add_development_dependency "rspec", ">= 2", "<= 2.5"
|
|
25
|
-
s.add_development_dependency "
|
|
25
|
+
s.add_development_dependency "webmock", ">= 1.6.2"
|
|
26
26
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'webmock/rspec'
|
|
2
|
+
|
|
3
|
+
module WebMockHelper
|
|
4
|
+
def mock_response(method, endpoint, response_file, options = {})
|
|
5
|
+
stub_request(method, endpoint).with(
|
|
6
|
+
request_for(method, options)
|
|
7
|
+
).to_return(
|
|
8
|
+
response_for(response_file, options)
|
|
9
|
+
)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def request_for(method, options = {})
|
|
15
|
+
request = {}
|
|
16
|
+
if options[:access_token]
|
|
17
|
+
options[:params] ||= {}
|
|
18
|
+
options[:params][:oauth_token] = options[:access_token].to_s
|
|
19
|
+
end
|
|
20
|
+
if options[:params]
|
|
21
|
+
case method
|
|
22
|
+
when :post, :put
|
|
23
|
+
request[:body] = options[:params]
|
|
24
|
+
else
|
|
25
|
+
request[:query] = options[:params]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
request
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def response_for(response_file, options = {})
|
|
32
|
+
response = {}
|
|
33
|
+
response[:body] = File.new(File.join(File.dirname(__FILE__), '../mock_response', response_file))
|
|
34
|
+
if options[:status]
|
|
35
|
+
response[:status] = options[:status]
|
|
36
|
+
end
|
|
37
|
+
response
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
include WebMockHelper
|
|
42
|
+
WebMock.disable_net_connect!
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Rack::OAuth2::AccessToken::Authenticator do
|
|
4
|
+
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
|
|
5
|
+
let(:request) { HTTP::Message.new_request(:get, URI.parse(resource_endpoint)) }
|
|
6
|
+
let(:authenticator) { Rack::OAuth2::AccessToken::Authenticator.new(token) }
|
|
7
|
+
|
|
8
|
+
shared_examples_for :authenticator do
|
|
9
|
+
it 'should let the token authenticate the request' do
|
|
10
|
+
token.should_receive(:authenticate).with(request)
|
|
11
|
+
authenticator.filter_request(request)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
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
|
+
context 'when Bearer token is given' do
|
|
25
|
+
let(:token) do
|
|
26
|
+
Rack::OAuth2::AccessToken::Bearer.new(
|
|
27
|
+
:access_token => 'access_token'
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
it_behaves_like :authenticator
|
|
31
|
+
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
|
+
end
|
|
@@ -7,37 +7,12 @@ 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
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
describe method.to_s.upcase do
|
|
17
|
-
it 'should have Bearer Authorization header' do
|
|
18
|
-
RestClient.should_receive(method).with(
|
|
19
|
-
resource_endpoint,
|
|
20
|
-
:AUTHORIZATION => 'Bearer access_token'
|
|
21
|
-
)
|
|
22
|
-
token.send method, resource_endpoint
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
[:post, :put].each do |method|
|
|
28
|
-
before do
|
|
29
|
-
fake_response(method, resource_endpoint, 'resources/fake.txt')
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
describe method.to_s.upcase do
|
|
33
|
-
it 'should have Bearer Authorization header' do
|
|
34
|
-
RestClient.should_receive(method).with(
|
|
35
|
-
resource_endpoint,
|
|
36
|
-
{:key => :value},
|
|
37
|
-
{:AUTHORIZATION => 'Bearer access_token'}
|
|
38
|
-
)
|
|
39
|
-
token.send method, resource_endpoint, {:key => :value}
|
|
40
|
-
end
|
|
12
|
+
describe '.authenticate' do
|
|
13
|
+
it 'should set Authorization header' do
|
|
14
|
+
request.header.should_receive(:[]=).with('Authorization', 'Bearer access_token')
|
|
15
|
+
token.authenticate(request)
|
|
41
16
|
end
|
|
42
17
|
end
|
|
43
18
|
end
|
|
@@ -7,42 +7,17 @@ describe Rack::OAuth2::AccessToken::Legacy do
|
|
|
7
7
|
)
|
|
8
8
|
end
|
|
9
9
|
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
|
|
10
|
-
|
|
11
|
-
[:get, :delete].each do |method|
|
|
12
|
-
before do
|
|
13
|
-
fake_response(method, resource_endpoint, 'resources/fake.txt')
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
describe method.to_s.upcase do
|
|
17
|
-
it 'should have OAuth2 Authorization header' do
|
|
18
|
-
RestClient.should_receive(method).with(
|
|
19
|
-
resource_endpoint,
|
|
20
|
-
:AUTHORIZATION => 'OAuth2 access_token'
|
|
21
|
-
)
|
|
22
|
-
token.send method, resource_endpoint
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
[:post, :put].each do |method|
|
|
28
|
-
before do
|
|
29
|
-
fake_response(method, resource_endpoint, 'resources/fake.txt')
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
describe method.to_s.upcase do
|
|
33
|
-
it 'should have OAuth2 Authorization header' do
|
|
34
|
-
RestClient.should_receive(method).with(
|
|
35
|
-
resource_endpoint,
|
|
36
|
-
{:key => :value},
|
|
37
|
-
{:AUTHORIZATION => 'OAuth2 access_token'}
|
|
38
|
-
)
|
|
39
|
-
token.send method, resource_endpoint, {:key => :value}
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
10
|
+
let(:request) { HTTPClient.new.send(:create_request, :post, URI.parse(resource_endpoint), {}, {:hello => "world"}, {}) }
|
|
43
11
|
|
|
44
12
|
describe '#to_s' do
|
|
45
13
|
subject { token }
|
|
46
14
|
its(:to_s) { should == token.access_token }
|
|
47
15
|
end
|
|
16
|
+
|
|
17
|
+
describe '.authenticate' do
|
|
18
|
+
it 'should set Authorization header' do
|
|
19
|
+
request.header.should_receive(:[]=).with('Authorization', 'OAuth2 access_token')
|
|
20
|
+
token.authenticate(request)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
48
23
|
end
|
|
@@ -5,9 +5,12 @@ describe Rack::OAuth2::AccessToken::MAC do
|
|
|
5
5
|
Rack::OAuth2::AccessToken::MAC.new(
|
|
6
6
|
:access_token => 'access_token',
|
|
7
7
|
:mac_key => 'secret',
|
|
8
|
-
:mac_algorithm => 'hmac-sha-256'
|
|
8
|
+
:mac_algorithm => 'hmac-sha-256',
|
|
9
|
+
:issued_at => issued_at
|
|
9
10
|
)
|
|
10
11
|
end
|
|
12
|
+
let(:issued_at) { 1305820455 }
|
|
13
|
+
let(:nonce) { '1000:51e74de734c05613f37520872e68db5f' }
|
|
11
14
|
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
|
|
12
15
|
subject { token }
|
|
13
16
|
|
|
@@ -26,63 +29,6 @@ describe Rack::OAuth2::AccessToken::MAC do
|
|
|
26
29
|
end
|
|
27
30
|
its(:generate_nonce) { should be_a String }
|
|
28
31
|
|
|
29
|
-
describe 'HTTP methods' do
|
|
30
|
-
before do
|
|
31
|
-
token.should_receive(:generate_nonce).and_return("51e74de734c05613f37520872e68db5f")
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
describe :GET do
|
|
35
|
-
let(:resource_endpoint) { 'https://server.example.com/resources/fake?key=value' }
|
|
36
|
-
it 'should have MAC Authorization header' do
|
|
37
|
-
Time.fix(Time.at(1302361200)) do
|
|
38
|
-
RestClient.should_receive(:get).with(
|
|
39
|
-
resource_endpoint,
|
|
40
|
-
:AUTHORIZATION => 'MAC id="access_token", nonce="51e74de734c05613f37520872e68db5f", mac="gMJ8AmvTGmfPFCJCf5DUwNTmT7ksw6GqyoGW2lUIUZ0="'
|
|
41
|
-
)
|
|
42
|
-
token.get resource_endpoint
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
describe :POST do
|
|
48
|
-
it 'should have MAC Authorization header' do
|
|
49
|
-
Time.fix(Time.at(1302361200)) do
|
|
50
|
-
RestClient.should_receive(:post).with(
|
|
51
|
-
resource_endpoint,
|
|
52
|
-
{:key => :value},
|
|
53
|
-
{:AUTHORIZATION => 'MAC id="access_token", nonce="51e74de734c05613f37520872e68db5f", bodyhash="Vj8DVxGNBe8UXWvd8pZswj6Gyo8vAT+RXlZa/fCfeiM=", mac="7OOseGqNi14lThhRnwhItACXACM4Qp5GleBEuizzUpw="'}
|
|
54
|
-
)
|
|
55
|
-
token.post resource_endpoint, :key => :value
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
describe :PUT do
|
|
61
|
-
it 'should have MAC Authorization header' do
|
|
62
|
-
Time.fix(Time.at(1302361200)) do
|
|
63
|
-
RestClient.should_receive(:put).with(
|
|
64
|
-
resource_endpoint,
|
|
65
|
-
{:key => :value},
|
|
66
|
-
{:AUTHORIZATION => 'MAC id="access_token", nonce="51e74de734c05613f37520872e68db5f", bodyhash="Vj8DVxGNBe8UXWvd8pZswj6Gyo8vAT+RXlZa/fCfeiM=", mac="lxTg/F29zkE7vBEbAK9VULRpM4IN5uShqHbj2k7e9lA="'}
|
|
67
|
-
)
|
|
68
|
-
token.put resource_endpoint, :key => :value
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
describe :DELETE do
|
|
74
|
-
it 'should have MAC Authorization header' do
|
|
75
|
-
Time.fix(Time.at(1302361200)) do
|
|
76
|
-
RestClient.should_receive(:delete).with(
|
|
77
|
-
resource_endpoint,
|
|
78
|
-
:AUTHORIZATION => 'MAC id="access_token", nonce="51e74de734c05613f37520872e68db5f", mac="JtOibEO1rBQNBGy6hUPT29L2cHSmLP09K+kUL4oEe/g="'
|
|
79
|
-
)
|
|
80
|
-
token.delete resource_endpoint
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
32
|
describe 'verify!' do
|
|
87
33
|
let(:request) { Rack::OAuth2::Server::Resource::MAC::Request.new(env) }
|
|
88
34
|
|
|
@@ -90,16 +36,14 @@ describe Rack::OAuth2::AccessToken::MAC do
|
|
|
90
36
|
let(:env) do
|
|
91
37
|
Rack::MockRequest.env_for(
|
|
92
38
|
'/protected_resources',
|
|
93
|
-
'HTTP_AUTHORIZATION' => %{MAC id="access_token", nonce="
|
|
39
|
+
'HTTP_AUTHORIZATION' => %{MAC id="access_token", nonce="#{nonce}", mac="#{signature}"}
|
|
94
40
|
)
|
|
95
41
|
end
|
|
96
42
|
|
|
97
43
|
context 'when signature is valid' do
|
|
98
|
-
let(:signature) { '
|
|
44
|
+
let(:signature) { 'nbQj0NdvSBKdwvw1yX6wpQ4EwrQKBg/r3lqwJGcthDU=' }
|
|
99
45
|
it do
|
|
100
|
-
|
|
101
|
-
token.verify!(request.setup!).should == :verified
|
|
102
|
-
end
|
|
46
|
+
token.verify!(request.setup!).should == :verified
|
|
103
47
|
end
|
|
104
48
|
end
|
|
105
49
|
|
|
@@ -122,7 +66,7 @@ describe Rack::OAuth2::AccessToken::MAC do
|
|
|
122
66
|
:params => {
|
|
123
67
|
:key1 => 'value1'
|
|
124
68
|
},
|
|
125
|
-
'HTTP_AUTHORIZATION' => %{MAC id="access_token", nonce="
|
|
69
|
+
'HTTP_AUTHORIZATION' => %{MAC id="access_token", nonce="#{nonce}", bodyhash="#{body_hash}", mac="#{signature}"}
|
|
126
70
|
)
|
|
127
71
|
end
|
|
128
72
|
let(:signature) { 'invalid' }
|
|
@@ -141,7 +85,7 @@ describe Rack::OAuth2::AccessToken::MAC do
|
|
|
141
85
|
let(:body_hash) { 'TPzUbFn1S16mpfmwXCi1L+8oZHRxlLX9/D1ZwAV781o=' }
|
|
142
86
|
|
|
143
87
|
context 'when signature is valid' do
|
|
144
|
-
let(:signature) { '
|
|
88
|
+
let(:signature) { 'ebFlQPMO3WzEZ3ncuIFnVK7IsVt+JEorQEEMJTiz/t8=' }
|
|
145
89
|
it do
|
|
146
90
|
Time.fix(Time.at(1302361200)) do
|
|
147
91
|
token.verify!(request.setup!).should == :verified
|
|
@@ -160,4 +104,16 @@ describe Rack::OAuth2::AccessToken::MAC do
|
|
|
160
104
|
end
|
|
161
105
|
end
|
|
162
106
|
end
|
|
107
|
+
|
|
108
|
+
describe '.authenticate' do
|
|
109
|
+
let(:request) { HTTPClient.new.send(:create_request, :post, URI.parse(resource_endpoint), {}, {:hello => "world"}, {}) }
|
|
110
|
+
let(:body_hash) { 'PQEeCVAqhFUqD4rhEtAkzCwRVZfjpXfV9JAHkCwiHcU=' }
|
|
111
|
+
let(:signature) { 'aL2Oh8gWrCAtJ/Xu6XMtJb6ZsYQT+GxQTs/TgJDQ7ZY=' }
|
|
112
|
+
|
|
113
|
+
it 'should set Authorization header' do
|
|
114
|
+
token.should_receive(:generate_nonce).and_return(nonce)
|
|
115
|
+
request.header.should_receive(:[]=).with('Authorization', "MAC id=\"access_token\", nonce=\"#{nonce}\", bodyhash=\"#{body_hash}\", mac=\"#{signature}\"")
|
|
116
|
+
token.authenticate(request)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
163
119
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Rack::OAuth2::AccessToken do
|
|
4
|
-
|
|
4
|
+
let :token do
|
|
5
5
|
Rack::OAuth2::AccessToken::Bearer.new(
|
|
6
6
|
:access_token => 'access_token',
|
|
7
7
|
:refresh_token => 'refresh_token',
|
|
@@ -9,6 +9,7 @@ describe Rack::OAuth2::AccessToken do
|
|
|
9
9
|
:scope => [:scope1, :scope2]
|
|
10
10
|
)
|
|
11
11
|
end
|
|
12
|
+
subject { token }
|
|
12
13
|
|
|
13
14
|
its(:access_token) { should == 'access_token' }
|
|
14
15
|
its(:refresh_token) { should == 'refresh_token' }
|
|
@@ -45,4 +46,15 @@ describe Rack::OAuth2::AccessToken do
|
|
|
45
46
|
end.should_not raise_error
|
|
46
47
|
end
|
|
47
48
|
end
|
|
49
|
+
|
|
50
|
+
let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
|
|
51
|
+
[:get, :delete, :post, :put].each do |method|
|
|
52
|
+
describe method do
|
|
53
|
+
it 'should delegate to HTTPClient with Authenticator filter' do
|
|
54
|
+
token.client.should_receive(method).with(resource_endpoint)
|
|
55
|
+
token.client.request_filter.last.should be_a Rack::OAuth2::AccessToken::Authenticator
|
|
56
|
+
token.send method, resource_endpoint
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
48
60
|
end
|
|
@@ -77,7 +77,7 @@ describe Rack::OAuth2::Client do
|
|
|
77
77
|
context 'when bearer token is given' do
|
|
78
78
|
before do
|
|
79
79
|
client.authorization_code = 'code'
|
|
80
|
-
|
|
80
|
+
mock_response(
|
|
81
81
|
:post,
|
|
82
82
|
'https://server.example.com/oauth2/token',
|
|
83
83
|
'tokens/bearer.json'
|
|
@@ -93,7 +93,7 @@ describe Rack::OAuth2::Client do
|
|
|
93
93
|
context 'when mac token is given' do
|
|
94
94
|
before do
|
|
95
95
|
client.authorization_code = 'code'
|
|
96
|
-
|
|
96
|
+
mock_response(
|
|
97
97
|
:post,
|
|
98
98
|
'https://server.example.com/oauth2/token',
|
|
99
99
|
'tokens/mac.json'
|
|
@@ -109,7 +109,7 @@ describe Rack::OAuth2::Client do
|
|
|
109
109
|
context 'when no-type token is given (JSON)' do
|
|
110
110
|
before do
|
|
111
111
|
client.authorization_code = 'code'
|
|
112
|
-
|
|
112
|
+
mock_response(
|
|
113
113
|
:post,
|
|
114
114
|
'https://server.example.com/oauth2/token',
|
|
115
115
|
'tokens/legacy.json'
|
|
@@ -124,7 +124,7 @@ describe Rack::OAuth2::Client do
|
|
|
124
124
|
|
|
125
125
|
context 'when no-type token is given (key-value)' do
|
|
126
126
|
before do
|
|
127
|
-
|
|
127
|
+
mock_response(
|
|
128
128
|
:post,
|
|
129
129
|
'https://server.example.com/oauth2/token',
|
|
130
130
|
'tokens/legacy.txt'
|
|
@@ -137,7 +137,7 @@ describe Rack::OAuth2::Client do
|
|
|
137
137
|
|
|
138
138
|
context 'when expires_in is not given' do
|
|
139
139
|
before do
|
|
140
|
-
|
|
140
|
+
mock_response(
|
|
141
141
|
:post,
|
|
142
142
|
'https://server.example.com/oauth2/token',
|
|
143
143
|
'tokens/legacy_without_expires_in.txt'
|
|
@@ -150,7 +150,7 @@ describe Rack::OAuth2::Client do
|
|
|
150
150
|
context 'when unknown-type token is given' do
|
|
151
151
|
before do
|
|
152
152
|
client.authorization_code = 'code'
|
|
153
|
-
|
|
153
|
+
mock_response(
|
|
154
154
|
:post,
|
|
155
155
|
'https://server.example.com/oauth2/token',
|
|
156
156
|
'tokens/unknown.json'
|
|
@@ -163,7 +163,7 @@ describe Rack::OAuth2::Client do
|
|
|
163
163
|
|
|
164
164
|
context 'when error response is given' do
|
|
165
165
|
before do
|
|
166
|
-
|
|
166
|
+
mock_response(
|
|
167
167
|
:post,
|
|
168
168
|
'https://server.example.com/oauth2/token',
|
|
169
169
|
'errors/invalid_request.json',
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,23 +1,10 @@
|
|
|
1
|
-
require 'rack/oauth2'
|
|
2
1
|
require 'rspec'
|
|
3
|
-
require '
|
|
2
|
+
require 'rack/oauth2'
|
|
4
3
|
require 'helpers/time'
|
|
4
|
+
require 'helpers/webmock_helper'
|
|
5
5
|
|
|
6
6
|
def simple_app
|
|
7
7
|
lambda do |env|
|
|
8
8
|
[ 200, {'Content-Type' => 'text/plain'}, ["HELLO"] ]
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
|
-
|
|
12
|
-
def fake_response(method, endpoint, file_path, options = {})
|
|
13
|
-
FakeWeb.register_uri(
|
|
14
|
-
method,
|
|
15
|
-
endpoint,
|
|
16
|
-
options.merge(
|
|
17
|
-
:body => File.read(
|
|
18
|
-
File.join(File.dirname(__FILE__), 'fake_response', file_path)
|
|
19
|
-
)
|
|
20
|
-
)
|
|
21
|
-
)
|
|
22
|
-
end
|
|
23
|
-
FakeWeb.allow_net_connect = false
|
metadata
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rack-oauth2
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
prerelease:
|
|
5
|
-
version: 0.
|
|
4
|
+
prerelease: 6
|
|
5
|
+
version: 0.8.0.alpha
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
8
8
|
- nov matake
|
|
@@ -10,7 +10,7 @@ autorequire:
|
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
12
|
|
|
13
|
-
date: 2011-05-
|
|
13
|
+
date: 2011-05-19 00:00:00 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: rack
|
|
@@ -35,14 +35,14 @@ dependencies:
|
|
|
35
35
|
type: :runtime
|
|
36
36
|
version_requirements: *id002
|
|
37
37
|
- !ruby/object:Gem::Dependency
|
|
38
|
-
name:
|
|
38
|
+
name: httpclient
|
|
39
39
|
prerelease: false
|
|
40
40
|
requirement: &id003 !ruby/object:Gem::Requirement
|
|
41
41
|
none: false
|
|
42
42
|
requirements:
|
|
43
43
|
- - ">="
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
|
-
version:
|
|
45
|
+
version: 2.2.0.2
|
|
46
46
|
type: :runtime
|
|
47
47
|
version_requirements: *id003
|
|
48
48
|
- !ruby/object:Gem::Dependency
|
|
@@ -115,14 +115,14 @@ dependencies:
|
|
|
115
115
|
type: :development
|
|
116
116
|
version_requirements: *id009
|
|
117
117
|
- !ruby/object:Gem::Dependency
|
|
118
|
-
name:
|
|
118
|
+
name: webmock
|
|
119
119
|
prerelease: false
|
|
120
120
|
requirement: &id010 !ruby/object:Gem::Requirement
|
|
121
121
|
none: false
|
|
122
122
|
requirements:
|
|
123
123
|
- - ">="
|
|
124
124
|
- !ruby/object:Gem::Version
|
|
125
|
-
version:
|
|
125
|
+
version: 1.6.2
|
|
126
126
|
type: :development
|
|
127
127
|
version_requirements: *id010
|
|
128
128
|
description: OAuth 2.0 Server & Client Library. Both Bearer and MAC token type are supported.
|
|
@@ -146,6 +146,7 @@ files:
|
|
|
146
146
|
- VERSION
|
|
147
147
|
- lib/rack/oauth2.rb
|
|
148
148
|
- lib/rack/oauth2/access_token.rb
|
|
149
|
+
- lib/rack/oauth2/access_token/authenticator.rb
|
|
149
150
|
- lib/rack/oauth2/access_token/bearer.rb
|
|
150
151
|
- lib/rack/oauth2/access_token/legacy.rb
|
|
151
152
|
- lib/rack/oauth2/access_token/mac.rb
|
|
@@ -183,15 +184,17 @@ files:
|
|
|
183
184
|
- lib/rack/oauth2/server/token/refresh_token.rb
|
|
184
185
|
- lib/rack/oauth2/util.rb
|
|
185
186
|
- rack-oauth2.gemspec
|
|
186
|
-
- spec/fake_response/errors/invalid_request.json
|
|
187
|
-
- spec/fake_response/resources/fake.txt
|
|
188
|
-
- spec/fake_response/tokens/bearer.json
|
|
189
|
-
- spec/fake_response/tokens/legacy.json
|
|
190
|
-
- spec/fake_response/tokens/legacy.txt
|
|
191
|
-
- spec/fake_response/tokens/legacy_without_expires_in.txt
|
|
192
|
-
- spec/fake_response/tokens/mac.json
|
|
193
|
-
- spec/fake_response/tokens/unknown.json
|
|
194
187
|
- spec/helpers/time.rb
|
|
188
|
+
- spec/helpers/webmock_helper.rb
|
|
189
|
+
- spec/mock_response/errors/invalid_request.json
|
|
190
|
+
- spec/mock_response/resources/fake.txt
|
|
191
|
+
- spec/mock_response/tokens/bearer.json
|
|
192
|
+
- spec/mock_response/tokens/legacy.json
|
|
193
|
+
- spec/mock_response/tokens/legacy.txt
|
|
194
|
+
- spec/mock_response/tokens/legacy_without_expires_in.txt
|
|
195
|
+
- spec/mock_response/tokens/mac.json
|
|
196
|
+
- spec/mock_response/tokens/unknown.json
|
|
197
|
+
- spec/rack/oauth2/access_token/authenticator_spec.rb
|
|
195
198
|
- spec/rack/oauth2/access_token/bearer_spec.rb
|
|
196
199
|
- spec/rack/oauth2/access_token/legacy_spec.rb
|
|
197
200
|
- spec/rack/oauth2/access_token/mac/body_hash_spec.rb
|
|
@@ -248,15 +251,17 @@ signing_key:
|
|
|
248
251
|
specification_version: 3
|
|
249
252
|
summary: OAuth 2.0 Server & Client Library - Both Bearer and MAC token type are supported
|
|
250
253
|
test_files:
|
|
251
|
-
- spec/fake_response/errors/invalid_request.json
|
|
252
|
-
- spec/fake_response/resources/fake.txt
|
|
253
|
-
- spec/fake_response/tokens/bearer.json
|
|
254
|
-
- spec/fake_response/tokens/legacy.json
|
|
255
|
-
- spec/fake_response/tokens/legacy.txt
|
|
256
|
-
- spec/fake_response/tokens/legacy_without_expires_in.txt
|
|
257
|
-
- spec/fake_response/tokens/mac.json
|
|
258
|
-
- spec/fake_response/tokens/unknown.json
|
|
259
254
|
- spec/helpers/time.rb
|
|
255
|
+
- spec/helpers/webmock_helper.rb
|
|
256
|
+
- spec/mock_response/errors/invalid_request.json
|
|
257
|
+
- spec/mock_response/resources/fake.txt
|
|
258
|
+
- spec/mock_response/tokens/bearer.json
|
|
259
|
+
- spec/mock_response/tokens/legacy.json
|
|
260
|
+
- spec/mock_response/tokens/legacy.txt
|
|
261
|
+
- spec/mock_response/tokens/legacy_without_expires_in.txt
|
|
262
|
+
- spec/mock_response/tokens/mac.json
|
|
263
|
+
- spec/mock_response/tokens/unknown.json
|
|
264
|
+
- spec/rack/oauth2/access_token/authenticator_spec.rb
|
|
260
265
|
- spec/rack/oauth2/access_token/bearer_spec.rb
|
|
261
266
|
- spec/rack/oauth2/access_token/legacy_spec.rb
|
|
262
267
|
- spec/rack/oauth2/access_token/mac/body_hash_spec.rb
|