rack-oauth2-revibe 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +22 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +20 -0
  8. data/README.rdoc +78 -0
  9. data/Rakefile +25 -0
  10. data/VERSION +1 -0
  11. data/lib/rack/oauth2.rb +67 -0
  12. data/lib/rack/oauth2/access_token.rb +36 -0
  13. data/lib/rack/oauth2/access_token/authenticator.rb +24 -0
  14. data/lib/rack/oauth2/access_token/bearer.rb +11 -0
  15. data/lib/rack/oauth2/access_token/legacy.rb +23 -0
  16. data/lib/rack/oauth2/access_token/mac.rb +103 -0
  17. data/lib/rack/oauth2/access_token/mac/sha256_hex_verifier.rb +17 -0
  18. data/lib/rack/oauth2/access_token/mac/signature.rb +34 -0
  19. data/lib/rack/oauth2/access_token/mac/verifier.rb +44 -0
  20. data/lib/rack/oauth2/client.rb +139 -0
  21. data/lib/rack/oauth2/client/error.rb +14 -0
  22. data/lib/rack/oauth2/client/grant.rb +30 -0
  23. data/lib/rack/oauth2/client/grant/authorization_code.rb +12 -0
  24. data/lib/rack/oauth2/client/grant/client_credentials.rb +10 -0
  25. data/lib/rack/oauth2/client/grant/facebook_token.rb +12 -0
  26. data/lib/rack/oauth2/client/grant/password.rb +11 -0
  27. data/lib/rack/oauth2/client/grant/refresh_token.rb +11 -0
  28. data/lib/rack/oauth2/debugger.rb +3 -0
  29. data/lib/rack/oauth2/debugger/request_filter.rb +30 -0
  30. data/lib/rack/oauth2/server.rb +4 -0
  31. data/lib/rack/oauth2/server/abstract.rb +4 -0
  32. data/lib/rack/oauth2/server/abstract/error.rb +69 -0
  33. data/lib/rack/oauth2/server/abstract/handler.rb +20 -0
  34. data/lib/rack/oauth2/server/abstract/request.rb +29 -0
  35. data/lib/rack/oauth2/server/abstract/response.rb +15 -0
  36. data/lib/rack/oauth2/server/authorize.rb +117 -0
  37. data/lib/rack/oauth2/server/authorize/code.rb +39 -0
  38. data/lib/rack/oauth2/server/authorize/error.rb +71 -0
  39. data/lib/rack/oauth2/server/authorize/extension.rb +12 -0
  40. data/lib/rack/oauth2/server/authorize/extension/code_and_token.rb +39 -0
  41. data/lib/rack/oauth2/server/authorize/token.rb +43 -0
  42. data/lib/rack/oauth2/server/resource.rb +55 -0
  43. data/lib/rack/oauth2/server/resource/bearer.rb +47 -0
  44. data/lib/rack/oauth2/server/resource/bearer/error.rb +24 -0
  45. data/lib/rack/oauth2/server/resource/error.rb +81 -0
  46. data/lib/rack/oauth2/server/resource/mac.rb +36 -0
  47. data/lib/rack/oauth2/server/resource/mac/error.rb +24 -0
  48. data/lib/rack/oauth2/server/token.rb +87 -0
  49. data/lib/rack/oauth2/server/token/authorization_code.rb +28 -0
  50. data/lib/rack/oauth2/server/token/client_credentials.rb +23 -0
  51. data/lib/rack/oauth2/server/token/error.rb +54 -0
  52. data/lib/rack/oauth2/server/token/extension.rb +12 -0
  53. data/lib/rack/oauth2/server/token/extension/jwt.rb +37 -0
  54. data/lib/rack/oauth2/server/token/facebook_token.rb +27 -0
  55. data/lib/rack/oauth2/server/token/password.rb +27 -0
  56. data/lib/rack/oauth2/server/token/refresh_token.rb +26 -0
  57. data/lib/rack/oauth2/util.rb +58 -0
  58. data/rack-oauth2.gemspec +30 -0
  59. data/spec/helpers/time.rb +19 -0
  60. data/spec/helpers/webmock_helper.rb +41 -0
  61. data/spec/mock_response/blank +0 -0
  62. data/spec/mock_response/errors/invalid_request.json +4 -0
  63. data/spec/mock_response/resources/fake.txt +1 -0
  64. data/spec/mock_response/tokens/_Bearer.json +6 -0
  65. data/spec/mock_response/tokens/bearer.json +6 -0
  66. data/spec/mock_response/tokens/legacy.json +5 -0
  67. data/spec/mock_response/tokens/legacy.txt +1 -0
  68. data/spec/mock_response/tokens/legacy_without_expires_in.txt +1 -0
  69. data/spec/mock_response/tokens/mac.json +8 -0
  70. data/spec/mock_response/tokens/unknown.json +6 -0
  71. data/spec/rack/oauth2/access_token/authenticator_spec.rb +43 -0
  72. data/spec/rack/oauth2/access_token/bearer_spec.rb +18 -0
  73. data/spec/rack/oauth2/access_token/legacy_spec.rb +23 -0
  74. data/spec/rack/oauth2/access_token/mac/sha256_hex_verifier_spec.rb +28 -0
  75. data/spec/rack/oauth2/access_token/mac/signature_spec.rb +59 -0
  76. data/spec/rack/oauth2/access_token/mac/verifier_spec.rb +25 -0
  77. data/spec/rack/oauth2/access_token/mac_spec.rb +141 -0
  78. data/spec/rack/oauth2/access_token_spec.rb +69 -0
  79. data/spec/rack/oauth2/client/error_spec.rb +18 -0
  80. data/spec/rack/oauth2/client/grant/authorization_code_spec.rb +37 -0
  81. data/spec/rack/oauth2/client/grant/client_credentials_spec.rb +7 -0
  82. data/spec/rack/oauth2/client/grant/password_spec.rb +33 -0
  83. data/spec/rack/oauth2/client/grant/refresh_token_spec.rb +21 -0
  84. data/spec/rack/oauth2/client_spec.rb +287 -0
  85. data/spec/rack/oauth2/debugger/request_filter_spec.rb +33 -0
  86. data/spec/rack/oauth2/oauth2_spec.rb +74 -0
  87. data/spec/rack/oauth2/server/abstract/error_spec.rb +59 -0
  88. data/spec/rack/oauth2/server/authorize/code_spec.rb +57 -0
  89. data/spec/rack/oauth2/server/authorize/error_spec.rb +103 -0
  90. data/spec/rack/oauth2/server/authorize/extensions/code_and_token_spec.rb +60 -0
  91. data/spec/rack/oauth2/server/authorize/token_spec.rb +73 -0
  92. data/spec/rack/oauth2/server/authorize_spec.rb +214 -0
  93. data/spec/rack/oauth2/server/resource/bearer/error_spec.rb +52 -0
  94. data/spec/rack/oauth2/server/resource/bearer_spec.rb +123 -0
  95. data/spec/rack/oauth2/server/resource/error_spec.rb +147 -0
  96. data/spec/rack/oauth2/server/resource/mac/error_spec.rb +52 -0
  97. data/spec/rack/oauth2/server/resource/mac_spec.rb +119 -0
  98. data/spec/rack/oauth2/server/resource_spec.rb +23 -0
  99. data/spec/rack/oauth2/server/token/authorization_code_spec.rb +43 -0
  100. data/spec/rack/oauth2/server/token/client_credentials_spec.rb +23 -0
  101. data/spec/rack/oauth2/server/token/error_spec.rb +77 -0
  102. data/spec/rack/oauth2/server/token/password_spec.rb +37 -0
  103. data/spec/rack/oauth2/server/token/refresh_token_spec.rb +34 -0
  104. data/spec/rack/oauth2/server/token_spec.rb +134 -0
  105. data/spec/rack/oauth2/util_spec.rb +97 -0
  106. data/spec/spec_helper.rb +14 -0
  107. metadata +326 -0
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::OAuth2::AccessToken::MAC::Verifier do
4
+ let(:verifier) { Rack::OAuth2::AccessToken::MAC::Verifier.new(:algorithm => algorithm) }
5
+ subject { verifier }
6
+
7
+ context 'when "hmac-sha-1" is specified' do
8
+ let(:algorithm) { 'hmac-sha-1' }
9
+ its(:hash_generator) { should be_instance_of OpenSSL::Digest::SHA1 }
10
+ end
11
+
12
+ context 'when "hmac-sha-256" is specified' do
13
+ let(:algorithm) { 'hmac-sha-256' }
14
+ its(:hash_generator) { should be_instance_of OpenSSL::Digest::SHA256 }
15
+ end
16
+
17
+ context 'otherwise' do
18
+ let(:algorithm) { 'invalid' }
19
+ it do
20
+ expect { verifier.send(:hash_generator) }.to raise_error(StandardError, 'Unsupported Algorithm')
21
+ end
22
+ end
23
+
24
+
25
+ end
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::OAuth2::AccessToken::MAC do
4
+ let(:ts) { 1305820234 }
5
+ let :token do
6
+ Rack::OAuth2::AccessToken::MAC.new(
7
+ :access_token => 'access_token',
8
+ :mac_key => 'secret',
9
+ :mac_algorithm => 'hmac-sha-256',
10
+ :ts => ts
11
+ )
12
+ end
13
+ let :token_with_ext_verifier do
14
+ Rack::OAuth2::AccessToken::MAC.new(
15
+ :access_token => 'access_token',
16
+ :mac_key => 'secret',
17
+ :mac_algorithm => 'hmac-sha-256',
18
+ :ts => ts,
19
+ :ext_verifier => Rack::OAuth2::AccessToken::MAC::Sha256HexVerifier
20
+ )
21
+ end
22
+ let(:nonce) { '1000:51e74de734c05613f37520872e68db5f' }
23
+ let(:resource_endpoint) { 'https://server.example.com/resources/fake' }
24
+ subject { token }
25
+
26
+ its(:mac_key) { should == 'secret' }
27
+ its(:mac_algorithm) { should == 'hmac-sha-256' }
28
+ its(:token_response) do
29
+ should == {
30
+ :access_token => 'access_token',
31
+ :refresh_token => nil,
32
+ :token_type => :mac,
33
+ :expires_in => nil,
34
+ :scope => '',
35
+ :mac_key => 'secret',
36
+ :mac_algorithm => 'hmac-sha-256'
37
+ }
38
+ end
39
+ its(:generate_nonce) { should be_a String }
40
+
41
+ describe 'verify!' do
42
+ let(:request) { Rack::OAuth2::Server::Resource::MAC::Request.new(env) }
43
+
44
+ context 'when no ext_verifier is given' do
45
+ let(:env) do
46
+ Rack::MockRequest.env_for(
47
+ '/protected_resources',
48
+ 'HTTP_AUTHORIZATION' => %{MAC id="access_token", nonce="#{nonce}", ts="#{ts}" mac="#{signature}"}
49
+ )
50
+ end
51
+
52
+ context 'when signature is valid' do
53
+ let(:signature) { 'BgooS/voPOZWLwoVfx4+zbC3xAVKW3jtjhKYOfIGZOA=' }
54
+ it do
55
+
56
+ token.verify!(request.setup!).should == :verified
57
+ end
58
+ end
59
+
60
+ context 'otherwise' do
61
+ let(:signature) { 'invalid' }
62
+ it do
63
+ expect { token.verify!(request.setup!) }.to raise_error(
64
+ Rack::OAuth2::Server::Resource::MAC::Unauthorized,
65
+ 'invalid_token :: Signature Invalid'
66
+ )
67
+ end
68
+ end
69
+ end
70
+
71
+ context 'when ext_verifier is given' do
72
+ let(:env) do
73
+ Rack::MockRequest.env_for(
74
+ '/protected_resources',
75
+ :method => :POST,
76
+ :params => {
77
+ :key1 => 'value1'
78
+ },
79
+ 'HTTP_AUTHORIZATION' => %{MAC id="access_token", nonce="#{nonce}", ts="#{ts}", mac="#{signature}", ext="#{ext}"}
80
+ )
81
+ end
82
+ let(:signature) { 'invalid' }
83
+
84
+ context 'when ext is invalid' do
85
+ let(:ext) { 'invalid' }
86
+ it do
87
+ expect { token_with_ext_verifier.verify!(request.setup!) }.to raise_error(
88
+ Rack::OAuth2::Server::Resource::MAC::Unauthorized,
89
+ 'invalid_token :: Sha256HexVerifier Invalid'
90
+ )
91
+ end
92
+ end
93
+
94
+ context 'when ext is valid' do
95
+ let(:ext) { '4cfcd46c59f54b5ea6a5f9b05c28b52fef2864747194b5fdfc3d59c0057bf35a' }
96
+
97
+ context 'when signature is valid' do
98
+ let(:signature) { 'dZYR54n+Lym5qCRRmDqmRZ71rG+bkjSWmqrOv8OjYHk=' }
99
+ it do
100
+ Time.fix(Time.at(1302361200)) do
101
+ token_with_ext_verifier.verify!(request.setup!).should == :verified
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'otherwise' do
107
+ it do
108
+ expect { token.verify!(request.setup!) }.to raise_error(
109
+ Rack::OAuth2::Server::Resource::MAC::Unauthorized,
110
+ 'invalid_token :: Signature Invalid'
111
+ )
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '.authenticate' do
119
+ let(:request) { HTTPClient.new.send(:create_request, :post, URI.parse(resource_endpoint), {}, {:hello => "world"}, {}) }
120
+ context 'when no ext_verifier is given' do
121
+ let(:signature) { 'pOBaL6HRawe4tUPmcU4vJEj1f2GJqrbQOlCcdAYgI/s=' }
122
+
123
+ it 'should set Authorization header' do
124
+ token.should_receive(:generate_nonce).and_return(nonce)
125
+ request.header.should_receive(:[]=).with('Authorization', "MAC id=\"access_token\", nonce=\"#{nonce}\", ts=\"#{ts.to_i}\", mac=\"#{signature}\"")
126
+ token.authenticate(request)
127
+ end
128
+ end
129
+
130
+ context 'when ext_verifier is given' do
131
+ let(:signature) { 'vgU0fj6rSpwUCAoCOrXlu8pZBR8a5Q5xIVlB4MCvJeM=' }
132
+ let(:ext) { '3d011e09502a84552a0f8ae112d024cc2c115597e3a577d5f49007902c221dc5' }
133
+ it 'should set Authorization header with ext_verifier' do
134
+ token_with_ext_verifier.should_receive(:generate_nonce).and_return(nonce)
135
+ request.header.should_receive(:[]=).with('Authorization', "MAC id=\"access_token\", nonce=\"#{nonce}\", ts=\"#{ts.to_i}\", mac=\"#{signature}\", ext=\"#{ext}\"")
136
+ token_with_ext_verifier.authenticate(request)
137
+ end
138
+ end
139
+
140
+ end
141
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::OAuth2::AccessToken do
4
+ let :token do
5
+ Rack::OAuth2::AccessToken::Bearer.new(
6
+ :access_token => 'access_token',
7
+ :refresh_token => 'refresh_token',
8
+ :expires_in => 3600,
9
+ :scope => [:scope1, :scope2]
10
+ )
11
+ end
12
+ subject { token }
13
+
14
+ its(:access_token) { should == 'access_token' }
15
+ its(:refresh_token) { should == 'refresh_token' }
16
+ its(:expires_in) { should == 3600 }
17
+ its(:scope) { should == [:scope1, :scope2] }
18
+ its(:token_response) do
19
+ should == {
20
+ :token_type => :bearer,
21
+ :access_token => 'access_token',
22
+ :refresh_token => 'refresh_token',
23
+ :expires_in => 3600,
24
+ :scope => 'scope1 scope2'
25
+ }
26
+ end
27
+
28
+ context 'when access_token is missing' do
29
+ it do
30
+ expect do
31
+ Rack::OAuth2::AccessToken::Bearer.new(
32
+ :refresh_token => 'refresh_token',
33
+ :expires_in => 3600,
34
+ :scope => [:scope1, :scope2]
35
+ )
36
+ end.to raise_error AttrRequired::AttrMissing
37
+ end
38
+ end
39
+
40
+ context 'otherwise' do
41
+ it do
42
+ expect do
43
+ Rack::OAuth2::AccessToken::Bearer.new(
44
+ :access_token => 'access_token'
45
+ )
46
+ end.not_to raise_error
47
+ end
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.httpclient.should_receive(method).with(resource_endpoint)
55
+ token.httpclient.request_filter.last.should be_a Rack::OAuth2::AccessToken::Authenticator
56
+ token.send method, resource_endpoint
57
+ end
58
+ end
59
+
60
+ context 'in debug mode' do
61
+ it do
62
+ Rack::OAuth2.debug do
63
+ token.httpclient.request_filter[-2].should be_a Rack::OAuth2::AccessToken::Authenticator
64
+ token.httpclient.request_filter.last.should be_a Rack::OAuth2::Debugger::RequestFilter
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Client::Error do
4
+ let :error do
5
+ {
6
+ :error => :invalid_request,
7
+ :error_description => 'Include invalid parameters',
8
+ :error_uri => 'http://server.example.com/error/invalid_request'
9
+ }
10
+ end
11
+ subject do
12
+ Rack::OAuth2::Client::Error.new 400, error
13
+ end
14
+
15
+ its(:status) { should == 400 }
16
+ its(:message) { should == error[:error_description] }
17
+ its(:response) { should == error }
18
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Client::Grant::AuthorizationCode do
4
+ let(:redirect_uri) { 'https://client.example.com/callback' }
5
+ let(:grant) { Rack::OAuth2::Client::Grant::AuthorizationCode }
6
+
7
+ context 'when code is given' do
8
+ let :attributes do
9
+ {:code => 'code'}
10
+ end
11
+
12
+ context 'when redirect_uri is given' do
13
+ let :attributes do
14
+ {:code => 'code', :redirect_uri => redirect_uri}
15
+ end
16
+ subject { grant.new attributes }
17
+ its(:redirect_uri) { should == redirect_uri }
18
+ its(:as_json) do
19
+ should == {:grant_type => :authorization_code, :code => 'code', :redirect_uri => redirect_uri}
20
+ end
21
+ end
22
+
23
+ context 'otherwise' do
24
+ subject { grant.new attributes }
25
+ its(:redirect_uri) { should be_nil }
26
+ its(:as_json) do
27
+ should == {:grant_type => :authorization_code, :code => 'code', :redirect_uri => nil}
28
+ end
29
+ end
30
+ end
31
+
32
+ context 'otherwise' do
33
+ it do
34
+ expect { grant.new }.to raise_error AttrRequired::AttrMissing
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Client::Grant::ClientCredentials do
4
+ its(:as_json) do
5
+ should == {:grant_type => :client_credentials}
6
+ end
7
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Client::Grant::Password do
4
+ let(:grant) { Rack::OAuth2::Client::Grant::Password }
5
+
6
+ context 'when username is given' do
7
+ let :attributes do
8
+ {:username => 'username'}
9
+ end
10
+
11
+ context 'when password is given' do
12
+ let :attributes do
13
+ {:username => 'username', :password => 'password'}
14
+ end
15
+ subject { grant.new attributes }
16
+ its(:as_json) do
17
+ should == {:grant_type => :password, :username => 'username', :password => 'password'}
18
+ end
19
+ end
20
+
21
+ context 'otherwise' do
22
+ it do
23
+ expect { grant.new attributes }.to raise_error AttrRequired::AttrMissing
24
+ end
25
+ end
26
+ end
27
+
28
+ context 'otherwise' do
29
+ it do
30
+ expect { grant.new }.to raise_error AttrRequired::AttrMissing
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Client::Grant::RefreshToken do
4
+ let(:grant) { Rack::OAuth2::Client::Grant::RefreshToken }
5
+
6
+ context 'when refresh_token is given' do
7
+ let :attributes do
8
+ {:refresh_token => 'refresh_token'}
9
+ end
10
+ subject { grant.new attributes }
11
+ its(:as_json) do
12
+ should == {:grant_type => :refresh_token, :refresh_token => 'refresh_token'}
13
+ end
14
+ end
15
+
16
+ context 'otherwise' do
17
+ it do
18
+ expect { grant.new }.to raise_error AttrRequired::AttrMissing
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,287 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Rack::OAuth2::Client do
4
+ let :client do
5
+ Rack::OAuth2::Client.new(
6
+ :identifier => 'client_id',
7
+ :secret => 'client_secret',
8
+ :host => 'server.example.com',
9
+ :redirect_uri => 'https://client.example.com/callback'
10
+ )
11
+ end
12
+ subject { client }
13
+
14
+ its(:identifier) { should == 'client_id' }
15
+ its(:secret) { should == 'client_secret' }
16
+ its(:authorization_endpoint) { should == '/oauth2/authorize' }
17
+ its(:token_endpoint) { should == '/oauth2/token' }
18
+
19
+ context 'when identifier is missing' do
20
+ it do
21
+ expect { Rack::OAuth2::Client.new }.to raise_error AttrRequired::AttrMissing
22
+ end
23
+ end
24
+
25
+ describe '#authorization_uri' do
26
+ subject { client.authorization_uri }
27
+ it { should include 'https://server.example.com/oauth2/authorize' }
28
+ it { should include 'client_id=client_id' }
29
+ it { should include 'redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback' }
30
+ it { should include 'response_type=code' }
31
+
32
+ context 'when endpoints are absolute URIs' do
33
+ before do
34
+ client.authorization_endpoint = 'https://server2.example.com/oauth/authorize'
35
+ client.token_endpoint = 'https://server2.example.com/oauth/token'
36
+ end
37
+ it { should include 'https://server2.example.com/oauth/authorize' }
38
+ end
39
+
40
+ context 'when scheme is specified' do
41
+ before { client.scheme = 'http' }
42
+ it { should include 'http://server.example.com/oauth2/authorize' }
43
+ end
44
+
45
+ context 'when response_type is token' do
46
+ subject { client.authorization_uri(:response_type => :token) }
47
+ it { should include 'response_type=token' }
48
+ end
49
+
50
+ context 'when response_type is an Array' do
51
+ subject { client.authorization_uri(:response_type => [:token, :code]) }
52
+ it { should include 'response_type=token+code' }
53
+ end
54
+
55
+ context 'when scope is given' do
56
+ subject { client.authorization_uri(:scope => [:scope1, :scope2]) }
57
+ it { should include 'scope=scope1+scope2' }
58
+ end
59
+ end
60
+
61
+ describe '#authorization_code=' do
62
+ before { client.authorization_code = 'code' }
63
+ subject { client.instance_variable_get('@grant') }
64
+ it { should be_instance_of Rack::OAuth2::Client::Grant::AuthorizationCode }
65
+ end
66
+
67
+ describe '#resource_owner_credentials=' do
68
+ before { client.resource_owner_credentials = 'username', 'password' }
69
+ subject { client.instance_variable_get('@grant') }
70
+ it { should be_instance_of Rack::OAuth2::Client::Grant::Password }
71
+ end
72
+
73
+ describe '#refresh_token=' do
74
+ before { client.refresh_token = 'refresh_token' }
75
+ subject { client.instance_variable_get('@grant') }
76
+ it { should be_instance_of Rack::OAuth2::Client::Grant::RefreshToken }
77
+ end
78
+
79
+ describe '#access_token!' do
80
+ subject { client.access_token! }
81
+
82
+ describe 'client authentication method' do
83
+ before do
84
+ client.authorization_code = 'code'
85
+ end
86
+
87
+ it 'should be Basic auth as default' do
88
+ mock_response(
89
+ :post,
90
+ 'https://server.example.com/oauth2/token',
91
+ 'tokens/bearer.json',
92
+ :request_header => {
93
+ 'Authorization' => 'Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ='
94
+ }
95
+ )
96
+ client.access_token!
97
+ end
98
+
99
+ context 'when other auth method specified' do
100
+ it do
101
+ mock_response(
102
+ :post,
103
+ 'https://server.example.com/oauth2/token',
104
+ 'tokens/bearer.json',
105
+ :params => {
106
+ :client_id => 'client_id',
107
+ :client_secret => 'client_secret',
108
+ :code => 'code',
109
+ :grant_type => 'authorization_code',
110
+ :redirect_uri => 'https://client.example.com/callback'
111
+ }
112
+ )
113
+ client.access_token! :client_auth_body
114
+ end
115
+ end
116
+ end
117
+
118
+ describe 'scopes' do
119
+ context 'when scope option given' do
120
+ it 'should specify given scope' do
121
+ mock_response(
122
+ :post,
123
+ 'https://server.example.com/oauth2/token',
124
+ 'tokens/bearer.json',
125
+ :params => {
126
+ :grant_type => 'client_credentials',
127
+ :scope => 'a b'
128
+ }
129
+ )
130
+ client.access_token! :scope => [:a, :b]
131
+ end
132
+ end
133
+ end
134
+
135
+ context 'when bearer token is given' do
136
+ before do
137
+ client.authorization_code = 'code'
138
+ mock_response(
139
+ :post,
140
+ 'https://server.example.com/oauth2/token',
141
+ 'tokens/bearer.json'
142
+ )
143
+ end
144
+ it { should be_instance_of Rack::OAuth2::AccessToken::Bearer }
145
+ its(:token_type) { should == :bearer }
146
+ its(:access_token) { should == 'access_token' }
147
+ its(:refresh_token) { should == 'refresh_token' }
148
+ its(:expires_in) { should == 3600 }
149
+
150
+ context 'when token type is "Bearer", not "bearer"' do
151
+ before do
152
+ client.authorization_code = 'code'
153
+ mock_response(
154
+ :post,
155
+ 'https://server.example.com/oauth2/token',
156
+ 'tokens/_Bearer.json'
157
+ )
158
+ end
159
+ it { should be_instance_of Rack::OAuth2::AccessToken::Bearer }
160
+ its(:token_type) { should == :bearer }
161
+ end
162
+ end
163
+
164
+ context 'when mac token is given' do
165
+ before do
166
+ client.authorization_code = 'code'
167
+ mock_response(
168
+ :post,
169
+ 'https://server.example.com/oauth2/token',
170
+ 'tokens/mac.json'
171
+ )
172
+ end
173
+ it { should be_instance_of Rack::OAuth2::AccessToken::MAC }
174
+ its(:token_type) { should == :mac }
175
+ its(:access_token) { should == 'access_token' }
176
+ its(:refresh_token) { should == 'refresh_token' }
177
+ its(:expires_in) { should == 3600 }
178
+ end
179
+
180
+ context 'when no-type token is given (JSON)' do
181
+ before do
182
+ client.authorization_code = 'code'
183
+ mock_response(
184
+ :post,
185
+ 'https://server.example.com/oauth2/token',
186
+ 'tokens/legacy.json'
187
+ )
188
+ end
189
+ it { should be_instance_of Rack::OAuth2::AccessToken::Legacy }
190
+ its(:token_type) { should == :legacy }
191
+ its(:access_token) { should == 'access_token' }
192
+ its(:refresh_token) { should == 'refresh_token' }
193
+ its(:expires_in) { should == 3600 }
194
+ end
195
+
196
+ context 'when no-type token is given (key-value)' do
197
+ before do
198
+ mock_response(
199
+ :post,
200
+ 'https://server.example.com/oauth2/token',
201
+ 'tokens/legacy.txt'
202
+ )
203
+ end
204
+ it { should be_instance_of Rack::OAuth2::AccessToken::Legacy }
205
+ its(:token_type) { should == :legacy }
206
+ its(:access_token) { should == 'access_token' }
207
+ its(:expires_in) { should == 3600 }
208
+
209
+ context 'when expires_in is not given' do
210
+ before do
211
+ mock_response(
212
+ :post,
213
+ 'https://server.example.com/oauth2/token',
214
+ 'tokens/legacy_without_expires_in.txt'
215
+ )
216
+ end
217
+ its(:expires_in) { should be_nil }
218
+ end
219
+ end
220
+
221
+ context 'when unknown-type token is given' do
222
+ before do
223
+ client.authorization_code = 'code'
224
+ mock_response(
225
+ :post,
226
+ 'https://server.example.com/oauth2/token',
227
+ 'tokens/unknown.json'
228
+ )
229
+ end
230
+ it do
231
+ expect { client.access_token! }.to raise_error(StandardError, 'Unknown Token Type')
232
+ end
233
+ end
234
+
235
+ context 'when error response is given' do
236
+ before do
237
+ mock_response(
238
+ :post,
239
+ 'https://server.example.com/oauth2/token',
240
+ 'errors/invalid_request.json',
241
+ :status => 400
242
+ )
243
+ end
244
+ it do
245
+ expect { client.access_token! }.to raise_error Rack::OAuth2::Client::Error
246
+ end
247
+ end
248
+
249
+ context 'when no body given' do
250
+ context 'when error given' do
251
+ before do
252
+ mock_response(
253
+ :post,
254
+ 'https://server.example.com/oauth2/token',
255
+ 'blank',
256
+ :status => 400
257
+ )
258
+ end
259
+ it do
260
+ expect { client.access_token! }.to raise_error Rack::OAuth2::Client::Error
261
+ end
262
+ end
263
+ end
264
+ end
265
+
266
+ context 'when no host info' do
267
+ let :client do
268
+ Rack::OAuth2::Client.new(
269
+ :identifier => 'client_id',
270
+ :secret => 'client_secret',
271
+ :redirect_uri => 'https://client.example.com/callback'
272
+ )
273
+ end
274
+
275
+ describe '#authorization_uri' do
276
+ it do
277
+ expect { client.authorization_uri }.to raise_error 'No Host Info'
278
+ end
279
+ end
280
+
281
+ describe '#access_token!' do
282
+ it do
283
+ expect { client.access_token! }.to raise_error 'No Host Info'
284
+ end
285
+ end
286
+ end
287
+ end