rack-oauth2 0.2.3 → 0.3.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.
Files changed (52) hide show
  1. data/Gemfile +1 -0
  2. data/README.rdoc +1 -0
  3. data/VERSION +1 -1
  4. data/lib/rack/oauth2.rb +1 -7
  5. data/lib/rack/oauth2/server.rb +0 -1
  6. data/lib/rack/oauth2/server/abstract.rb +2 -1
  7. data/lib/rack/oauth2/server/abstract/error.rb +55 -0
  8. data/lib/rack/oauth2/server/abstract/handler.rb +2 -3
  9. data/lib/rack/oauth2/server/abstract/request.rb +2 -3
  10. data/lib/rack/oauth2/server/abstract/response.rb +0 -5
  11. data/lib/rack/oauth2/server/authorize.rb +19 -14
  12. data/lib/rack/oauth2/server/authorize/code.rb +8 -19
  13. data/lib/rack/oauth2/server/authorize/error.rb +60 -0
  14. data/lib/rack/oauth2/server/authorize/token.rb +15 -24
  15. data/lib/rack/oauth2/server/resource.rb +1 -79
  16. data/lib/rack/oauth2/server/resource/bearer.rb +74 -0
  17. data/lib/rack/oauth2/server/resource/bearer/error.rb +80 -0
  18. data/lib/rack/oauth2/server/token.rb +12 -19
  19. data/lib/rack/oauth2/server/token/authorization_code.rb +4 -5
  20. data/lib/rack/oauth2/server/token/error.rb +54 -0
  21. data/lib/rack/oauth2/server/token/password.rb +0 -2
  22. data/lib/rack/oauth2/server/token/refresh_token.rb +1 -1
  23. data/lib/rack/oauth2/server/util.rb +29 -0
  24. data/rack-oauth2.gemspec +1 -1
  25. data/spec/rack/oauth2/server/abstract/error_spec.rb +51 -0
  26. data/spec/rack/oauth2/server/authorize/code_spec.rb +42 -28
  27. data/spec/rack/oauth2/server/authorize/error_spec.rb +103 -0
  28. data/spec/rack/oauth2/server/authorize/token_spec.rb +55 -26
  29. data/spec/rack/oauth2/server/authorize_spec.rb +24 -68
  30. data/spec/rack/oauth2/server/resource/bearer/error_spec.rb +118 -0
  31. data/spec/rack/oauth2/server/resource/bearer_spec.rb +117 -0
  32. data/spec/rack/oauth2/server/token/authorization_code_spec.rb +26 -109
  33. data/spec/rack/oauth2/server/token/error_spec.rb +77 -0
  34. data/spec/rack/oauth2/server/token/password_spec.rb +27 -47
  35. data/spec/rack/oauth2/server/token/refresh_token_spec.rb +22 -43
  36. data/spec/rack/oauth2/server/token_spec.rb +77 -116
  37. data/spec/rack/oauth2/server/util_spec.rb +75 -16
  38. data/spec/spec_helper.rb +0 -12
  39. metadata +25 -29
  40. data/lib/rack/oauth2/server/authorize/code_and_token.rb +0 -62
  41. data/lib/rack/oauth2/server/error.rb +0 -73
  42. data/lib/rack/oauth2/server/error/authorize.rb +0 -54
  43. data/lib/rack/oauth2/server/error/resource.rb +0 -50
  44. data/lib/rack/oauth2/server/error/token.rb +0 -59
  45. data/lib/rack/oauth2/server/token/assertion.rb +0 -29
  46. data/spec/rack/oauth2/server/authorize/code_and_token_spec.rb +0 -53
  47. data/spec/rack/oauth2/server/error/authorize_spec.rb +0 -102
  48. data/spec/rack/oauth2/server/error/resource_spec.rb +0 -69
  49. data/spec/rack/oauth2/server/error/token_spec.rb +0 -115
  50. data/spec/rack/oauth2/server/error_spec.rb +0 -107
  51. data/spec/rack/oauth2/server/resource_spec.rb +0 -141
  52. data/spec/rack/oauth2/server/token/assertion_spec.rb +0 -56
@@ -0,0 +1,117 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Server::Resource::Bearer do
4
+ let(:app) do
5
+ Rack::OAuth2::Server::Resource::Bearer.new(simple_app) do |request|
6
+ case request.access_token
7
+ when 'valid_token'
8
+ # nothing to do
9
+ when 'insufficient_scope_token'
10
+ request.insufficient_scope!
11
+ else
12
+ request.invalid_token!
13
+ end
14
+ end
15
+ end
16
+ let(:access_token) { env[Rack::OAuth2::Server::Resource::Bearer::ACCESS_TOKEN] }
17
+ let(:request) { app.call(env) }
18
+ subject { app.call(env) }
19
+
20
+ shared_examples_for :non_oauth2_request do
21
+ it 'should skip OAuth 2.0 authentication' do
22
+ status, header, response = request
23
+ status.should == 200
24
+ access_token.should be_nil
25
+ end
26
+ end
27
+ shared_examples_for :authenticated_request do
28
+ it 'should be authenticated' do
29
+ status, header, response = request
30
+ status.should == 200
31
+ access_token.should == 'valid_token'
32
+ end
33
+ end
34
+ shared_examples_for :unauthorized_request do
35
+ it 'should be unauthorized' do
36
+ status, header, response = request
37
+ status.should == 401
38
+ header['WWW-Authenticate'].should include 'Bearer'
39
+ access_token.should be_nil
40
+ end
41
+ end
42
+ shared_examples_for :bad_request do
43
+ it 'should be unauthorized' do
44
+ status, header, response = request
45
+ status.should == 400
46
+ access_token.should be_nil
47
+ end
48
+ end
49
+
50
+ context 'when no access token is given' do
51
+ let(:env) { Rack::MockRequest.env_for('/protected_resource') }
52
+ it_behaves_like :non_oauth2_request
53
+ end
54
+
55
+ context 'when valid_token is given' do
56
+ context 'when token is in Authorization header' do
57
+ let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'Bearer valid_token') }
58
+ it_behaves_like :authenticated_request
59
+ end
60
+
61
+ context 'when token is in params' do
62
+ let(:env) { Rack::MockRequest.env_for('/protected_resource', :params => {:oauth_token => 'valid_token'}) }
63
+ it_behaves_like :authenticated_request
64
+ end
65
+ end
66
+
67
+ context 'when invalid_token is given' do
68
+ context 'when token is in Authorization header' do
69
+ let(:env) { Rack::MockRequest.env_for('/protected_resource', 'HTTP_AUTHORIZATION' => 'Bearer invalid_token') }
70
+ it_behaves_like :unauthorized_request
71
+ end
72
+
73
+ context 'when token is in params' do
74
+ let(:env) { Rack::MockRequest.env_for('/protected_resource', :params => {:oauth_token => 'invalid_token'}) }
75
+ it_behaves_like :unauthorized_request
76
+ end
77
+ end
78
+
79
+ context 'when multiple access_token is given' do
80
+ context 'when token is in Authorization header and params' do
81
+ let(:env) do
82
+ Rack::MockRequest.env_for(
83
+ '/protected_resource',
84
+ 'HTTP_AUTHORIZATION' => 'Bearer valid_token',
85
+ :params => {:oauth_token => 'valid_token'}
86
+ )
87
+ end
88
+ it_behaves_like :bad_request
89
+ end
90
+ end
91
+
92
+ context 'when OAuth 1.0 request' do
93
+ context 'when token is in Authorization header' do
94
+ let(:env) do
95
+ Rack::MockRequest.env_for(
96
+ '/protected_resource',
97
+ 'HTTP_AUTHORIZATION' => 'OAuth oauth_consumer_key="key" oauth_token="token" oauth_signature_method="HMAC-SHA1" oauth_signature="sig" oauth_timestamp="123456789" oauth_nonce="nonce"'
98
+ )
99
+ end
100
+ it_behaves_like :non_oauth2_request
101
+ end
102
+
103
+ context 'when token is in params' do
104
+ let(:env) do
105
+ Rack::MockRequest.env_for('/protected_resource', :params => {
106
+ :oauth_consumer_key => 'key',
107
+ :oauth_token => 'token',
108
+ :oauth_signature_method => 'HMAC-SHA1',
109
+ :oauth_signature => 'sig',
110
+ :oauth_timestamp => 123456789,
111
+ :oauth_nonce => 'nonce'
112
+ })
113
+ end
114
+ it_behaves_like :non_oauth2_request
115
+ end
116
+ end
117
+ end
@@ -1,119 +1,36 @@
1
1
  require 'spec_helper.rb'
2
2
 
3
3
  describe Rack::OAuth2::Server::Token::AuthorizationCode do
4
-
5
- context "when valid code is given" do
6
-
7
- before do
8
- @app = Rack::OAuth2::Server::Token.new(simple_app) do |request, response|
9
- response.access_token = "access_token"
10
- end
11
- @request = Rack::MockRequest.new @app
4
+ let(:request) { Rack::MockRequest.new app }
5
+ let(:app) do
6
+ Rack::OAuth2::Server::Token.new do |request, response|
7
+ response.access_token = 'access_token'
12
8
  end
13
-
14
- it "should return access_token as json response body" do
15
- response = @request.post("/", :params => {
16
- :grant_type => "authorization_code",
17
- :client_id => "valid_client",
18
- :code => "valid_authorization_code",
19
- :redirect_uri => "http://client.example.com/callback"
20
- })
21
- response.status.should == 200
22
- response.content_type.should == "application/json"
23
- response.body.should == {
24
- :access_token => "access_token"
25
- }.to_json
26
- end
27
-
28
9
  end
29
-
30
- context "when invalid code is given" do
31
-
32
- before do
33
- @app = Rack::OAuth2::Server::Token.new(simple_app) do |request, response|
34
- request.invalid_grant!('Invalid authorization code.')
35
- end
36
- @request = Rack::MockRequest.new @app
37
- end
38
-
39
- it "should return error message as json response body" do
40
- response = @request.post("/", :params => {
41
- :grant_type => "authorization_code",
42
- :client_id => "valid_client",
43
- :code => "invalid_authorization_code",
44
- :redirect_uri => "http://client.example.com/callback"
45
- })
46
- response.status.should == 400
47
- response.content_type.should == "application/json"
48
- response.body.should == {
49
- :error => :invalid_grant,
50
- :error_description => "Invalid authorization code."
51
- }.to_json
52
- end
53
-
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
+ }
54
17
  end
55
-
56
- context "when invalid client_id is given" do
57
-
58
- before do
59
- @app = Rack::OAuth2::Server::Token.new(simple_app) do |request, response|
60
- request.invalid_client!('Invalid client identifier.')
18
+ subject { request.post('/', :params => params) }
19
+
20
+ its(:status) { should == 200 }
21
+ its(:content_type) { should == 'application/json' }
22
+ its(:body) { should == '{"access_token":"access_token"}' }
23
+
24
+ [:code, :redirect_uri].each do |required|
25
+ context "when #{required} is missing" do
26
+ before do
27
+ params.delete_if do |key, value|
28
+ key == required
29
+ end
61
30
  end
62
- @request = Rack::MockRequest.new @app
31
+ its(:status) { should == 400 }
32
+ its(:content_type) { should == 'application/json' }
33
+ its(:body) { should include '"error":"invalid_request"' }
63
34
  end
64
-
65
- context "when client credentials is given via Authorization header" do
66
- it "should return 401 error" do
67
- response = @request.post("/", :params => {
68
- :grant_type => "authorization_code",
69
- :code => "valid_authorization_code",
70
- :redirect_uri => "http://client.example.com/callback"
71
- }, 'HTTP_AUTHORIZATION' => "Basic #{["invalid_client_id:client_secret"].pack("m*")}")
72
- response.status.should == 401
73
- response.content_type.should == "application/json"
74
- response.body.should == {
75
- :error => :invalid_client,
76
- :error_description => "Invalid client identifier."
77
- }.to_json
78
- end
79
- end
80
-
81
- context "when client credentials is given via request body" do
82
- it "should return 400 error" do
83
- response = @request.post("/", :params => {
84
- :grant_type => "authorization_code",
85
- :client_id => "invalid_client",
86
- :code => "valid_authorization_code",
87
- :redirect_uri => "http://client.example.com/callback"
88
- })
89
- response.status.should == 400
90
- response.content_type.should == "application/json"
91
- response.body.should == {
92
- :error => :invalid_client,
93
- :error_description => "Invalid client identifier."
94
- }.to_json
95
- end
96
- end
97
-
98
- context "when client credentials is given via both Authorization header and request body" do
99
- it "should return 401 error with multiple credentials error message" do
100
- response = @request.post("/", :params => {
101
- :grant_type => "authorization_code",
102
- :client_id => "invalid_client",
103
- :code => "valid_authorization_code",
104
- :redirect_uri => "http://client.example.com/callback"
105
- }, 'HTTP_AUTHORIZATION' => "Basic #{["invalid_client_id:client_secret"].pack("m*")}")
106
- response.status.should == 401
107
- response.content_type.should == "application/json"
108
- response.body.should == {
109
- :error => :invalid_client,
110
- :error_description => "Multiple client credentials are provided."
111
- }.to_json
112
- end
113
- # TODO
114
-
115
- end
116
-
117
35
  end
118
-
119
36
  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 }.should raise_error bad_request
45
+ end
46
+ end
47
+
48
+ describe 'unauthorized!' do
49
+ it do
50
+ expect { request.unauthorized! :invalid_client }.should 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 }.should 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 }.should 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
@@ -1,56 +1,36 @@
1
1
  require 'spec_helper.rb'
2
2
 
3
3
  describe Rack::OAuth2::Server::Token::Password do
4
-
5
- context "when valid resource owner credentials are given" do
6
-
7
- before do
8
- @app = Rack::OAuth2::Server::Token.new(simple_app) do |request, response|
9
- response.access_token = "access_token"
10
- end
11
- @request = Rack::MockRequest.new @app
4
+ let(:request) { Rack::MockRequest.new app }
5
+ let(:app) do
6
+ Rack::OAuth2::Server::Token.new do |request, response|
7
+ response.access_token = 'access_token'
12
8
  end
13
-
14
- it "should return access_token as json response body" do
15
- response = @request.post("/", :params => {
16
- :grant_type => "password",
17
- :client_id => "valid_client",
18
- :username => "nov",
19
- :password => "valid_pass"
20
- })
21
- response.status.should == 200
22
- response.content_type.should == "application/json"
23
- response.body.should == {
24
- :access_token => "access_token"
25
- }.to_json
26
- end
27
-
28
9
  end
29
-
30
- context "when invalid resource owner credentials are given" do
31
-
32
- before do
33
- @app = Rack::OAuth2::Server::Token.new(simple_app) do |request, response|
34
- request.invalid_grant! 'Invalid resource owner credentials.'
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 == '{"access_token":"access_token"}' }
23
+
24
+ [:username, :password].each do |required|
25
+ context "when #{required} is missing" do
26
+ before do
27
+ params.delete_if do |key, value|
28
+ key == required
29
+ end
35
30
  end
36
- @request = Rack::MockRequest.new @app
37
- end
38
-
39
- it "should return error message as json response body" do
40
- response = @request.post("/", :params => {
41
- :grant_type => "password",
42
- :client_id => "valid_client",
43
- :username => "nov",
44
- :password => "invalid_pass"
45
- })
46
- response.status.should == 400
47
- response.content_type.should == "application/json"
48
- response.body.should == {
49
- :error => :invalid_grant,
50
- :error_description => "Invalid resource owner credentials."
51
- }.to_json
31
+ its(:status) { should == 400 }
32
+ its(:content_type) { should == 'application/json' }
33
+ its(:body) { should include '"error":"invalid_request"' }
52
34
  end
53
-
54
35
  end
55
-
56
36
  end
@@ -1,54 +1,33 @@
1
1
  require 'spec_helper.rb'
2
2
 
3
3
  describe Rack::OAuth2::Server::Token::RefreshToken do
4
-
5
- context "when valid refresh_token is given" do
6
-
7
- before do
8
- @app = Rack::OAuth2::Server::Token.new(simple_app) do |request, response|
9
- response.access_token = "access_token"
10
- end
11
- @request = Rack::MockRequest.new @app
12
- end
13
-
14
- it "should return access_token as json response body" do
15
- response = @request.post("/", :params => {
16
- :grant_type => "refresh_token",
17
- :client_id => "valid_client",
18
- :refresh_token => "valid_refresh_token"
19
- })
20
- response.status.should == 200
21
- response.content_type.should == "application/json"
22
- response.body.should == {
23
- :access_token => "access_token"
24
- }.to_json
4
+ let(:request) { Rack::MockRequest.new app }
5
+ let(:app) do
6
+ Rack::OAuth2::Server::Token.new do |request, response|
7
+ response.access_token = 'access_token'
25
8
  end
26
-
27
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) }
28
18
 
29
- context "when invalid refresh_token is given" do
19
+ its(:status) { should == 200 }
20
+ its(:content_type) { should == 'application/json' }
21
+ its(:body) { should == '{"access_token":"access_token"}' }
30
22
 
23
+ context 'when refresh_token is missing' do
31
24
  before do
32
- @app = Rack::OAuth2::Server::Token.new(simple_app) do |request, response|
33
- request.invalid_grant! 'Invalid refresh_token.'
25
+ params.delete_if do |key, value|
26
+ key == :refresh_token
34
27
  end
35
- @request = Rack::MockRequest.new @app
36
- end
37
-
38
- it "should return error message as json response body" do
39
- response = @request.post("/", :params => {
40
- :grant_type => "refresh_token",
41
- :client_id => "valid_client",
42
- :refresh_token => "invalid_refresh_token"
43
- })
44
- response.status.should == 400
45
- response.content_type.should == "application/json"
46
- response.body.should == {
47
- :error => :invalid_grant,
48
- :error_description => "Invalid refresh_token."
49
- }.to_json
50
28
  end
51
-
29
+ its(:status) { should == 400 }
30
+ its(:content_type) { should == 'application/json' }
31
+ its(:body) { should include '"error":"invalid_request"' }
52
32
  end
53
-
54
- end
33
+ end