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.
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