rack-oauth2-revibe 1.0.7
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 +7 -0
- data/.document +5 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +78 -0
- data/Rakefile +25 -0
- data/VERSION +1 -0
- data/lib/rack/oauth2.rb +67 -0
- data/lib/rack/oauth2/access_token.rb +36 -0
- data/lib/rack/oauth2/access_token/authenticator.rb +24 -0
- data/lib/rack/oauth2/access_token/bearer.rb +11 -0
- data/lib/rack/oauth2/access_token/legacy.rb +23 -0
- data/lib/rack/oauth2/access_token/mac.rb +103 -0
- data/lib/rack/oauth2/access_token/mac/sha256_hex_verifier.rb +17 -0
- data/lib/rack/oauth2/access_token/mac/signature.rb +34 -0
- data/lib/rack/oauth2/access_token/mac/verifier.rb +44 -0
- data/lib/rack/oauth2/client.rb +139 -0
- data/lib/rack/oauth2/client/error.rb +14 -0
- data/lib/rack/oauth2/client/grant.rb +30 -0
- data/lib/rack/oauth2/client/grant/authorization_code.rb +12 -0
- data/lib/rack/oauth2/client/grant/client_credentials.rb +10 -0
- data/lib/rack/oauth2/client/grant/facebook_token.rb +12 -0
- data/lib/rack/oauth2/client/grant/password.rb +11 -0
- data/lib/rack/oauth2/client/grant/refresh_token.rb +11 -0
- data/lib/rack/oauth2/debugger.rb +3 -0
- data/lib/rack/oauth2/debugger/request_filter.rb +30 -0
- data/lib/rack/oauth2/server.rb +4 -0
- data/lib/rack/oauth2/server/abstract.rb +4 -0
- data/lib/rack/oauth2/server/abstract/error.rb +69 -0
- data/lib/rack/oauth2/server/abstract/handler.rb +20 -0
- data/lib/rack/oauth2/server/abstract/request.rb +29 -0
- data/lib/rack/oauth2/server/abstract/response.rb +15 -0
- data/lib/rack/oauth2/server/authorize.rb +117 -0
- data/lib/rack/oauth2/server/authorize/code.rb +39 -0
- data/lib/rack/oauth2/server/authorize/error.rb +71 -0
- data/lib/rack/oauth2/server/authorize/extension.rb +12 -0
- data/lib/rack/oauth2/server/authorize/extension/code_and_token.rb +39 -0
- data/lib/rack/oauth2/server/authorize/token.rb +43 -0
- data/lib/rack/oauth2/server/resource.rb +55 -0
- data/lib/rack/oauth2/server/resource/bearer.rb +47 -0
- data/lib/rack/oauth2/server/resource/bearer/error.rb +24 -0
- data/lib/rack/oauth2/server/resource/error.rb +81 -0
- data/lib/rack/oauth2/server/resource/mac.rb +36 -0
- data/lib/rack/oauth2/server/resource/mac/error.rb +24 -0
- data/lib/rack/oauth2/server/token.rb +87 -0
- data/lib/rack/oauth2/server/token/authorization_code.rb +28 -0
- data/lib/rack/oauth2/server/token/client_credentials.rb +23 -0
- data/lib/rack/oauth2/server/token/error.rb +54 -0
- data/lib/rack/oauth2/server/token/extension.rb +12 -0
- data/lib/rack/oauth2/server/token/extension/jwt.rb +37 -0
- data/lib/rack/oauth2/server/token/facebook_token.rb +27 -0
- data/lib/rack/oauth2/server/token/password.rb +27 -0
- data/lib/rack/oauth2/server/token/refresh_token.rb +26 -0
- data/lib/rack/oauth2/util.rb +58 -0
- data/rack-oauth2.gemspec +30 -0
- data/spec/helpers/time.rb +19 -0
- data/spec/helpers/webmock_helper.rb +41 -0
- data/spec/mock_response/blank +0 -0
- data/spec/mock_response/errors/invalid_request.json +4 -0
- data/spec/mock_response/resources/fake.txt +1 -0
- data/spec/mock_response/tokens/_Bearer.json +6 -0
- data/spec/mock_response/tokens/bearer.json +6 -0
- data/spec/mock_response/tokens/legacy.json +5 -0
- data/spec/mock_response/tokens/legacy.txt +1 -0
- data/spec/mock_response/tokens/legacy_without_expires_in.txt +1 -0
- data/spec/mock_response/tokens/mac.json +8 -0
- data/spec/mock_response/tokens/unknown.json +6 -0
- data/spec/rack/oauth2/access_token/authenticator_spec.rb +43 -0
- data/spec/rack/oauth2/access_token/bearer_spec.rb +18 -0
- data/spec/rack/oauth2/access_token/legacy_spec.rb +23 -0
- data/spec/rack/oauth2/access_token/mac/sha256_hex_verifier_spec.rb +28 -0
- data/spec/rack/oauth2/access_token/mac/signature_spec.rb +59 -0
- data/spec/rack/oauth2/access_token/mac/verifier_spec.rb +25 -0
- data/spec/rack/oauth2/access_token/mac_spec.rb +141 -0
- data/spec/rack/oauth2/access_token_spec.rb +69 -0
- data/spec/rack/oauth2/client/error_spec.rb +18 -0
- data/spec/rack/oauth2/client/grant/authorization_code_spec.rb +37 -0
- data/spec/rack/oauth2/client/grant/client_credentials_spec.rb +7 -0
- data/spec/rack/oauth2/client/grant/password_spec.rb +33 -0
- data/spec/rack/oauth2/client/grant/refresh_token_spec.rb +21 -0
- data/spec/rack/oauth2/client_spec.rb +287 -0
- data/spec/rack/oauth2/debugger/request_filter_spec.rb +33 -0
- data/spec/rack/oauth2/oauth2_spec.rb +74 -0
- data/spec/rack/oauth2/server/abstract/error_spec.rb +59 -0
- data/spec/rack/oauth2/server/authorize/code_spec.rb +57 -0
- data/spec/rack/oauth2/server/authorize/error_spec.rb +103 -0
- data/spec/rack/oauth2/server/authorize/extensions/code_and_token_spec.rb +60 -0
- data/spec/rack/oauth2/server/authorize/token_spec.rb +73 -0
- data/spec/rack/oauth2/server/authorize_spec.rb +214 -0
- data/spec/rack/oauth2/server/resource/bearer/error_spec.rb +52 -0
- data/spec/rack/oauth2/server/resource/bearer_spec.rb +123 -0
- data/spec/rack/oauth2/server/resource/error_spec.rb +147 -0
- data/spec/rack/oauth2/server/resource/mac/error_spec.rb +52 -0
- data/spec/rack/oauth2/server/resource/mac_spec.rb +119 -0
- data/spec/rack/oauth2/server/resource_spec.rb +23 -0
- data/spec/rack/oauth2/server/token/authorization_code_spec.rb +43 -0
- data/spec/rack/oauth2/server/token/client_credentials_spec.rb +23 -0
- data/spec/rack/oauth2/server/token/error_spec.rb +77 -0
- data/spec/rack/oauth2/server/token/password_spec.rb +37 -0
- data/spec/rack/oauth2/server/token/refresh_token_spec.rb +34 -0
- data/spec/rack/oauth2/server/token_spec.rb +134 -0
- data/spec/rack/oauth2/util_spec.rb +97 -0
- data/spec/spec_helper.rb +14 -0
- metadata +326 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Rack::OAuth2::Server::Resource::MAC::Unauthorized do
|
4
|
+
let(:error) { Rack::OAuth2::Server::Resource::MAC::Unauthorized.new(:invalid_token) }
|
5
|
+
|
6
|
+
it { should be_a Rack::OAuth2::Server::Resource::Unauthorized }
|
7
|
+
|
8
|
+
describe '#scheme' do
|
9
|
+
subject { error }
|
10
|
+
its(:scheme) { should == :MAC }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#finish' do
|
14
|
+
it 'should use MAC scheme' do
|
15
|
+
status, header, response = error.finish
|
16
|
+
header['WWW-Authenticate'].should =~ /^MAC /
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Rack::OAuth2::Server::Resource::MAC::ErrorMethods do
|
22
|
+
let(:unauthorized) { Rack::OAuth2::Server::Resource::MAC::Unauthorized }
|
23
|
+
let(:redirect_uri) { 'http://client.example.com/callback' }
|
24
|
+
let(:default_description) { Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION }
|
25
|
+
let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
|
26
|
+
let(:request) { Rack::OAuth2::Server::Resource::MAC::Request.new env }
|
27
|
+
|
28
|
+
describe 'unauthorized!' do
|
29
|
+
it do
|
30
|
+
expect { request.unauthorized! :invalid_client }.to raise_error unauthorized
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Rack::OAuth2::Server::Resource::Bearer::ErrorMethods::DEFAULT_DESCRIPTION.keys.each do |error_code|
|
35
|
+
method = "#{error_code}!"
|
36
|
+
case error_code
|
37
|
+
when :invalid_request
|
38
|
+
# ignore
|
39
|
+
when :insufficient_scope
|
40
|
+
# ignore
|
41
|
+
else
|
42
|
+
describe method do
|
43
|
+
it "should raise Rack::OAuth2::Server::Resource::Bearer::Unauthorized with error = :#{error_code}" do
|
44
|
+
expect { request.send method }.to raise_error(unauthorized) { |error|
|
45
|
+
error.error.should == error_code
|
46
|
+
error.description.should == default_description[error_code]
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Rack::OAuth2::Server::Resource::MAC do
|
4
|
+
let(:app) do
|
5
|
+
Rack::OAuth2::Server::Resource::MAC.new(simple_app) do |request|
|
6
|
+
case request.access_token
|
7
|
+
when 'valid_token'
|
8
|
+
token = mac_token
|
9
|
+
token.verify!(request)
|
10
|
+
token
|
11
|
+
when 'insufficient_scope_token'
|
12
|
+
request.insufficient_scope!
|
13
|
+
else
|
14
|
+
request.invalid_token!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
let(:mac_token) do
|
19
|
+
Rack::OAuth2::AccessToken::MAC.new(
|
20
|
+
:access_token => 'valid_token',
|
21
|
+
:mac_key => 'secret',
|
22
|
+
:mac_algorithm => 'hmac-sha-256',
|
23
|
+
:ts => 1305820230 # fix verification time
|
24
|
+
)
|
25
|
+
end
|
26
|
+
let(:access_token) { env[Rack::OAuth2::Server::Resource::ACCESS_TOKEN] }
|
27
|
+
let(:request) { app.call(env) }
|
28
|
+
subject { app.call(env) }
|
29
|
+
|
30
|
+
shared_examples_for :non_mac_request do
|
31
|
+
it 'should skip OAuth 2.0 authentication' do
|
32
|
+
status, header, response = request
|
33
|
+
status.should == 200
|
34
|
+
access_token.should be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
shared_examples_for :authenticated_mac_request do
|
38
|
+
it 'should be authenticated' do
|
39
|
+
status, header, response = request
|
40
|
+
status.should == 200
|
41
|
+
access_token.should == mac_token
|
42
|
+
end
|
43
|
+
end
|
44
|
+
shared_examples_for :unauthorized_mac_request do
|
45
|
+
it 'should be unauthorized' do
|
46
|
+
status, header, response = request
|
47
|
+
status.should == 401
|
48
|
+
header['WWW-Authenticate'].should include 'MAC'
|
49
|
+
access_token.should be_nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
shared_examples_for :bad_mac_request do
|
53
|
+
it 'should be unauthorized' do
|
54
|
+
status, header, response = request
|
55
|
+
status.should == 400
|
56
|
+
access_token.should be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when no access token is given' do
|
61
|
+
let(:env) { Rack::MockRequest.env_for('/protected_resource') }
|
62
|
+
it 'should skip OAuth 2.0 authentication' do
|
63
|
+
status, header, response = request
|
64
|
+
status.should == 200
|
65
|
+
access_token.should be_nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when valid_token is given' do
|
70
|
+
context 'when other required params are missing' do
|
71
|
+
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="valid_token"') }
|
72
|
+
it_behaves_like :unauthorized_mac_request
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when other required params are invalid' do
|
76
|
+
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="valid_token", nonce="51e74de734c05613f37520872e68db5f", ts="1305820234", mac="invalid""') }
|
77
|
+
it_behaves_like :unauthorized_mac_request
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when all required params are valid' do
|
81
|
+
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="valid_token", nonce="51e74de734c05613f37520872e68db5f", ts="1305820234", mac="26JP6MMZyAHLHeMU8+m+NbVJgZbikp5SlT86/a62pwg="') }
|
82
|
+
it_behaves_like :authenticated_mac_request
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when all required params are valid and ts is expired' do
|
86
|
+
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="valid_token", nonce="51e74de734c05613f37520872e68db5f", ts="1305819234", mac="nuo4765MZrVL/qMsAtuTczhqZAE5y02ChaLCyOiVU68="') }
|
87
|
+
it_behaves_like :unauthorized_mac_request
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'when invalid_token is given' do
|
92
|
+
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="invalid_token"') }
|
93
|
+
it_behaves_like :unauthorized_mac_request
|
94
|
+
|
95
|
+
describe 'realm' do
|
96
|
+
let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'MAC id="invalid_token"') }
|
97
|
+
|
98
|
+
context 'when specified' do
|
99
|
+
let(:realm) { 'server.example.com' }
|
100
|
+
let(:app) do
|
101
|
+
Rack::OAuth2::Server::Resource::MAC.new(simple_app, realm) do |request|
|
102
|
+
request.unauthorized!
|
103
|
+
end
|
104
|
+
end
|
105
|
+
it 'should use specified realm' do
|
106
|
+
status, header, response = request
|
107
|
+
header['WWW-Authenticate'].should include "MAC realm=\"#{realm}\""
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'otherwize' do
|
112
|
+
it 'should use default realm' do
|
113
|
+
status, header, response = request
|
114
|
+
header['WWW-Authenticate'].should include "MAC realm=\"#{Rack::OAuth2::Server::Resource::DEFAULT_REALM}\""
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Rack::OAuth2::Server::Resource do
|
4
|
+
subject { Rack::OAuth2::Server::Resource.new(simple_app, 'realm') }
|
5
|
+
its(:realm) { should == 'realm' }
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Rack::OAuth2::Server::Resource::Request do
|
9
|
+
let(:env) { Rack::MockRequest.env_for('/protected_resource') }
|
10
|
+
let(:request) { Rack::OAuth2::Server::Resource::Request.new(env) }
|
11
|
+
|
12
|
+
describe '#setup!' do
|
13
|
+
it do
|
14
|
+
expect { request.setup! }.to raise_error(RuntimeError, 'Define me!')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#oauth2?' do
|
19
|
+
it do
|
20
|
+
expect { request.oauth2? }.to raise_error(RuntimeError, 'Define me!')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Rack::OAuth2::Server::Token::AuthorizationCode do
|
4
|
+
let(:request) { Rack::MockRequest.new app }
|
5
|
+
let(:app) do
|
6
|
+
Rack::OAuth2::Server::Token.new do |request, response|
|
7
|
+
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(:access_token => 'access_token')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
let(:params) do
|
11
|
+
{
|
12
|
+
:grant_type => 'authorization_code',
|
13
|
+
:client_id => 'client_id',
|
14
|
+
:code => 'authorization_code',
|
15
|
+
:redirect_uri => 'http://client.example.com/callback'
|
16
|
+
}
|
17
|
+
end
|
18
|
+
let(:response) { request.post('/', :params => params) }
|
19
|
+
subject { response }
|
20
|
+
|
21
|
+
its(:status) { should == 200 }
|
22
|
+
its(:content_type) { should == 'application/json' }
|
23
|
+
its(:body) { should include '"access_token":"access_token"' }
|
24
|
+
its(:body) { should include '"token_type":"bearer"' }
|
25
|
+
|
26
|
+
it 'should prevent to be cached' do
|
27
|
+
response.header['Cache-Control'].should == 'no-store'
|
28
|
+
response.header['Pragma'].should == 'no-cache'
|
29
|
+
end
|
30
|
+
|
31
|
+
[:code].each do |required|
|
32
|
+
context "when #{required} is missing" do
|
33
|
+
before do
|
34
|
+
params.delete_if do |key, value|
|
35
|
+
key == required
|
36
|
+
end
|
37
|
+
end
|
38
|
+
its(:status) { should == 400 }
|
39
|
+
its(:content_type) { should == 'application/json' }
|
40
|
+
its(:body) { should include '"error":"invalid_request"' }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Rack::OAuth2::Server::Token::ClientCredentials do
|
4
|
+
let(:request) { Rack::MockRequest.new app }
|
5
|
+
let(:app) do
|
6
|
+
Rack::OAuth2::Server::Token.new do |request, response|
|
7
|
+
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(:access_token => 'access_token')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
let(:params) do
|
11
|
+
{
|
12
|
+
:grant_type => 'client_credentials',
|
13
|
+
:client_id => 'client_id',
|
14
|
+
:client_secret => 'client_secret'
|
15
|
+
}
|
16
|
+
end
|
17
|
+
subject { request.post('/', :params => params) }
|
18
|
+
|
19
|
+
its(:status) { should == 200 }
|
20
|
+
its(:content_type) { should == 'application/json' }
|
21
|
+
its(:body) { should include '"access_token":"access_token"' }
|
22
|
+
its(:body) { should include '"token_type":"bearer"' }
|
23
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Rack::OAuth2::Server::Token::BadRequest do
|
4
|
+
let(:error) { Rack::OAuth2::Server::Token::BadRequest.new(:invalid_request) }
|
5
|
+
|
6
|
+
it { should be_a Rack::OAuth2::Server::Abstract::BadRequest }
|
7
|
+
|
8
|
+
describe '#finish' do
|
9
|
+
it 'should respond in JSON' do
|
10
|
+
status, header, response = error.finish
|
11
|
+
status.should == 400
|
12
|
+
header['Content-Type'].should == 'application/json'
|
13
|
+
response.body.should == ['{"error":"invalid_request"}']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe Rack::OAuth2::Server::Token::Unauthorized do
|
19
|
+
let(:error) { Rack::OAuth2::Server::Token::Unauthorized.new(:invalid_request) }
|
20
|
+
|
21
|
+
it { should be_a Rack::OAuth2::Server::Abstract::Unauthorized }
|
22
|
+
|
23
|
+
describe '#finish' do
|
24
|
+
it 'should respond in JSON' do
|
25
|
+
status, header, response = error.finish
|
26
|
+
status.should == 401
|
27
|
+
header['Content-Type'].should == 'application/json'
|
28
|
+
header['WWW-Authenticate'].should == 'Basic realm="OAuth2 Token Endpoint"'
|
29
|
+
response.body.should == ['{"error":"invalid_request"}']
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Rack::OAuth2::Server::Token::ErrorMethods do
|
35
|
+
let(:bad_request) { Rack::OAuth2::Server::Token::BadRequest }
|
36
|
+
let(:unauthorized) { Rack::OAuth2::Server::Token::Unauthorized }
|
37
|
+
let(:redirect_uri) { 'http://client.example.com/callback' }
|
38
|
+
let(:default_description) { Rack::OAuth2::Server::Token::ErrorMethods::DEFAULT_DESCRIPTION }
|
39
|
+
let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
|
40
|
+
let(:request) { Rack::OAuth2::Server::Token::Request.new env }
|
41
|
+
|
42
|
+
describe 'bad_request!' do
|
43
|
+
it do
|
44
|
+
expect { request.bad_request! :invalid_request }.to raise_error bad_request
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'unauthorized!' do
|
49
|
+
it do
|
50
|
+
expect { request.unauthorized! :invalid_client }.to raise_error unauthorized
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Rack::OAuth2::Server::Token::ErrorMethods::DEFAULT_DESCRIPTION.keys.each do |error_code|
|
55
|
+
method = "#{error_code}!"
|
56
|
+
case error_code
|
57
|
+
when :invalid_client
|
58
|
+
describe method do
|
59
|
+
it "should raise Rack::OAuth2::Server::Token::Unauthorized with error = :#{error_code}" do
|
60
|
+
expect { request.send method }.to raise_error(unauthorized) { |error|
|
61
|
+
error.error.should == error_code
|
62
|
+
error.description.should == default_description[error_code]
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
else
|
67
|
+
describe method do
|
68
|
+
it "should raise Rack::OAuth2::Server::Token::BadRequest with error = :#{error_code}" do
|
69
|
+
expect { request.send method }.to raise_error(bad_request) { |error|
|
70
|
+
error.error.should == error_code
|
71
|
+
error.description.should == default_description[error_code]
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Rack::OAuth2::Server::Token::Password do
|
4
|
+
let(:request) { Rack::MockRequest.new app }
|
5
|
+
let(:app) do
|
6
|
+
Rack::OAuth2::Server::Token.new do |request, response|
|
7
|
+
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(:access_token => 'access_token')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
let(:params) do
|
11
|
+
{
|
12
|
+
:grant_type => 'password',
|
13
|
+
:client_id => 'client_id',
|
14
|
+
:username => 'nov',
|
15
|
+
:password => 'secret'
|
16
|
+
}
|
17
|
+
end
|
18
|
+
subject { request.post('/', :params => params) }
|
19
|
+
|
20
|
+
its(:status) { should == 200 }
|
21
|
+
its(:content_type) { should == 'application/json' }
|
22
|
+
its(:body) { should include '"access_token":"access_token"' }
|
23
|
+
its(:body) { should include '"token_type":"bearer"' }
|
24
|
+
|
25
|
+
[:username, :password].each do |required|
|
26
|
+
context "when #{required} is missing" do
|
27
|
+
before do
|
28
|
+
params.delete_if do |key, value|
|
29
|
+
key == required
|
30
|
+
end
|
31
|
+
end
|
32
|
+
its(:status) { should == 400 }
|
33
|
+
its(:content_type) { should == 'application/json' }
|
34
|
+
its(:body) { should include '"error":"invalid_request"' }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Rack::OAuth2::Server::Token::RefreshToken do
|
4
|
+
let(:request) { Rack::MockRequest.new app }
|
5
|
+
let(:app) do
|
6
|
+
Rack::OAuth2::Server::Token.new do |request, response|
|
7
|
+
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(:access_token => 'access_token')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
let(:params) do
|
11
|
+
{
|
12
|
+
:grant_type => "refresh_token",
|
13
|
+
:client_id => "client_id",
|
14
|
+
:refresh_token => "refresh_token"
|
15
|
+
}
|
16
|
+
end
|
17
|
+
subject { request.post('/', :params => params) }
|
18
|
+
|
19
|
+
its(:status) { should == 200 }
|
20
|
+
its(:content_type) { should == 'application/json' }
|
21
|
+
its(:body) { should include '"access_token":"access_token"' }
|
22
|
+
its(:body) { should include '"token_type":"bearer"' }
|
23
|
+
|
24
|
+
context 'when refresh_token is missing' do
|
25
|
+
before do
|
26
|
+
params.delete_if do |key, value|
|
27
|
+
key == :refresh_token
|
28
|
+
end
|
29
|
+
end
|
30
|
+
its(:status) { should == 400 }
|
31
|
+
its(:content_type) { should == 'application/json' }
|
32
|
+
its(:body) { should include '"error":"invalid_request"' }
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
describe Rack::OAuth2::Server::Token do
|
5
|
+
let(:request) { Rack::MockRequest.new app }
|
6
|
+
let(:app) do
|
7
|
+
Rack::OAuth2::Server::Token.new do |request, response|
|
8
|
+
response.access_token = Rack::OAuth2::AccessToken::Bearer.new(:access_token => 'access_token')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
let(:params) do
|
12
|
+
{
|
13
|
+
:grant_type => 'authorization_code',
|
14
|
+
:client_id => 'client_id',
|
15
|
+
:code => 'authorization_code',
|
16
|
+
:redirect_uri => 'http://client.example.com/callback'
|
17
|
+
}
|
18
|
+
end
|
19
|
+
subject { request.post('/token', :params => params) }
|
20
|
+
|
21
|
+
context 'when multiple client credentials are given' do
|
22
|
+
context 'when different credentials are given' do
|
23
|
+
let(:env) do
|
24
|
+
Rack::MockRequest.env_for(
|
25
|
+
'/token',
|
26
|
+
'HTTP_AUTHORIZATION' => "Basic #{Base64.encode64('client_id2:client_secret')}",
|
27
|
+
:params => params
|
28
|
+
)
|
29
|
+
end
|
30
|
+
it 'should fail with unsupported_grant_type' do
|
31
|
+
status, header, response = app.call(env)
|
32
|
+
status.should == 400
|
33
|
+
response.body.first.should include '"error":"invalid_request"'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when same credentials are given' do
|
38
|
+
let(:env) do
|
39
|
+
Rack::MockRequest.env_for(
|
40
|
+
'/token',
|
41
|
+
'HTTP_AUTHORIZATION' => "Basic #{Base64.encode64('client_id:client_secret')}",
|
42
|
+
:params => params
|
43
|
+
)
|
44
|
+
end
|
45
|
+
it 'should ignore duplicates' do
|
46
|
+
status, header, response = app.call(env)
|
47
|
+
status.should == 200
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when unsupported grant_type is given' do
|
53
|
+
before do
|
54
|
+
params.merge!(:grant_type => 'unknown')
|
55
|
+
end
|
56
|
+
its(:status) { should == 400 }
|
57
|
+
its(:content_type) { should == 'application/json' }
|
58
|
+
its(:body) { should include '"error":"unsupported_grant_type"' }
|
59
|
+
end
|
60
|
+
|
61
|
+
[:client_id, :grant_type].each do |required|
|
62
|
+
context "when #{required} is missing" do
|
63
|
+
before do
|
64
|
+
params.delete_if do |key, value|
|
65
|
+
key == required
|
66
|
+
end
|
67
|
+
end
|
68
|
+
its(:status) { should == 400 }
|
69
|
+
its(:content_type) { should == 'application/json' }
|
70
|
+
its(:body) { should include '"error":"invalid_request"' }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
Rack::OAuth2::Server::Token::ErrorMethods::DEFAULT_DESCRIPTION.each do |error, default_message|
|
75
|
+
status = if error == :invalid_client
|
76
|
+
401
|
77
|
+
else
|
78
|
+
400
|
79
|
+
end
|
80
|
+
context "when #{error}" do
|
81
|
+
let(:app) do
|
82
|
+
Rack::OAuth2::Server::Token.new do |request, response|
|
83
|
+
request.send "#{error}!"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
its(:status) { should == status }
|
87
|
+
its(:content_type) { should == 'application/json' }
|
88
|
+
its(:body) { should include "\"error\":\"#{error}\"" }
|
89
|
+
its(:body) { should include "\"error_description\":\"#{default_message}\"" }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when responding' do
|
94
|
+
context 'when access_token is missing' do
|
95
|
+
let(:app) do
|
96
|
+
Rack::OAuth2::Server::Token.new
|
97
|
+
end
|
98
|
+
it do
|
99
|
+
expect { request.post('/', :params => params) }.to raise_error AttrRequired::AttrMissing
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'extensibility' do
|
105
|
+
before do
|
106
|
+
require 'rack/oauth2/server/token/extension/jwt'
|
107
|
+
end
|
108
|
+
|
109
|
+
subject { app }
|
110
|
+
let(:env) do
|
111
|
+
Rack::MockRequest.env_for(
|
112
|
+
'/token',
|
113
|
+
:params => params
|
114
|
+
)
|
115
|
+
end
|
116
|
+
let(:request) { Rack::OAuth2::Server::Token::Request.new env }
|
117
|
+
its(:extensions) { should == [Rack::OAuth2::Server::Token::Extension::JWT] }
|
118
|
+
|
119
|
+
describe 'JWT assertion' do
|
120
|
+
let(:params) do
|
121
|
+
{
|
122
|
+
:grant_type => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
|
123
|
+
:assertion => 'header.payload.signature'
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
it do
|
128
|
+
app.send(
|
129
|
+
:grant_type_for, request
|
130
|
+
).should == Rack::OAuth2::Server::Token::Extension::JWT
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|