signet 0.5.1 → 0.6.0
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 +13 -5
- data/CHANGELOG.md +7 -0
- data/Gemfile +2 -19
- data/lib/signet/oauth_2/client.rb +82 -50
- data/lib/signet/oauth_2.rb +9 -2
- data/lib/signet/version.rb +2 -2
- data/signet.gemspec +38 -0
- data/spec/signet/oauth_1/client_spec.rb +231 -243
- data/spec/signet/oauth_1/credential_spec.rb +30 -30
- data/spec/signet/oauth_1/server_spec.rb +128 -129
- data/spec/signet/oauth_1/services/google_spec.rb +24 -25
- data/spec/signet/oauth_1/signature_methods/hmac_sha1_spec.rb +4 -4
- data/spec/signet/oauth_1/signature_methods/plaintext_spec.rb +4 -4
- data/spec/signet/oauth_1/signature_methods/rsa_sha1_spec.rb +6 -6
- data/spec/signet/oauth_1_spec.rb +190 -192
- data/spec/signet/oauth_2/client_spec.rb +296 -181
- data/spec/signet/oauth_2_spec.rb +58 -48
- data/spec/signet_spec.rb +23 -23
- data/spec/spec_helper.rb +3 -1
- data/tasks/gem.rake +3 -55
- data/tasks/spec.rake +0 -25
- metadata +99 -38
data/spec/signet/oauth_2_spec.rb
CHANGED
@@ -27,66 +27,66 @@ describe Signet::OAuth2 do
|
|
27
27
|
parameters = Signet::OAuth2.parse_authorization_header(
|
28
28
|
'Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW'
|
29
29
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
30
|
-
parameters['client_id'].
|
31
|
-
parameters['client_secret'].
|
30
|
+
expect(parameters['client_id']).to eq 's6BhdRkqt3'
|
31
|
+
expect(parameters['client_secret']).to eq 'gX1fBat3bV'
|
32
32
|
end
|
33
33
|
|
34
34
|
it 'should correctly handle OAuth auth-scheme' do
|
35
35
|
parameters = Signet::OAuth2.parse_authorization_header(
|
36
36
|
'OAuth vF9dft4qmT'
|
37
37
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
38
|
-
parameters['access_token'].
|
38
|
+
expect(parameters['access_token']).to eq 'vF9dft4qmT'
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'should correctly handle OAuth auth-scheme with realm' do
|
42
42
|
parameters = Signet::OAuth2.parse_authorization_header(
|
43
43
|
'OAuth vF9dft4qmT, realm="http://sp.example.com/"'
|
44
44
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
45
|
-
parameters['access_token'].
|
46
|
-
parameters['realm'].
|
45
|
+
expect(parameters['access_token']).to eq 'vF9dft4qmT'
|
46
|
+
expect(parameters['realm']).to eq 'http://sp.example.com/'
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'should correctly handle OAuth auth-scheme with multiple auth-params' do
|
50
50
|
parameters = Signet::OAuth2.parse_authorization_header(
|
51
51
|
'OAuth vF9dft4qmT, first="one", second="two"'
|
52
52
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
53
|
-
parameters['access_token'].
|
54
|
-
parameters['first'].
|
55
|
-
parameters['second'].
|
53
|
+
expect(parameters['access_token']).to eq 'vF9dft4qmT'
|
54
|
+
expect(parameters['first']).to eq 'one'
|
55
|
+
expect(parameters['second']).to eq 'two'
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'should liberally handle auth-params with single-quoted strings' do
|
59
59
|
parameters = Signet::OAuth2.parse_authorization_header(
|
60
60
|
'OAuth vF9dft4qmT, first=\'one\', second=\'two\''
|
61
61
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
62
|
-
parameters['access_token'].
|
63
|
-
parameters['first'].
|
64
|
-
parameters['second'].
|
62
|
+
expect(parameters['access_token']).to eq 'vF9dft4qmT'
|
63
|
+
expect(parameters['first']).to eq 'one'
|
64
|
+
expect(parameters['second']).to eq 'two'
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'should liberally handle auth-params with unquoted strings' do
|
68
68
|
parameters = Signet::OAuth2.parse_authorization_header(
|
69
69
|
'OAuth vF9dft4qmT, first=one, second=two'
|
70
70
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
71
|
-
parameters['access_token'].
|
72
|
-
parameters['first'].
|
73
|
-
parameters['second'].
|
71
|
+
expect(parameters['access_token']).to eq 'vF9dft4qmT'
|
72
|
+
expect(parameters['first']).to eq 'one'
|
73
|
+
expect(parameters['second']).to eq 'two'
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'should not allow unquoted strings that do not match tchar' do
|
77
|
-
(lambda do
|
77
|
+
expect(lambda do
|
78
78
|
parameters = Signet::OAuth2.parse_authorization_header(
|
79
79
|
'OAuth vF9dft4qmT, first=one:1'
|
80
80
|
)
|
81
|
-
end).
|
81
|
+
end).to raise_error(Signet::ParseError)
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'should not parse non-OAuth auth-schemes' do
|
85
|
-
(lambda do
|
85
|
+
expect(lambda do
|
86
86
|
Signet::OAuth2.parse_authorization_header(
|
87
87
|
'AuthSub token="GD32CMCL25aZ-v____8B"'
|
88
88
|
)
|
89
|
-
end).
|
89
|
+
end).to raise_error(Signet::ParseError)
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
@@ -97,9 +97,9 @@ describe Signet::OAuth2 do
|
|
97
97
|
'OAuth realm="http://sp.example.com/", error="expired_token", ' +
|
98
98
|
'error_description="The access token has expired."'
|
99
99
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
100
|
-
parameters['realm'].
|
101
|
-
parameters['error'].
|
102
|
-
parameters['error_description'].
|
100
|
+
expect(parameters['realm']).to eq 'http://sp.example.com/'
|
101
|
+
expect(parameters['error']).to eq 'expired_token'
|
102
|
+
expect(parameters['error_description']).to eq 'The access token has expired.'
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'should liberally handle auth-params with single-quoted strings' do
|
@@ -107,9 +107,9 @@ describe Signet::OAuth2 do
|
|
107
107
|
'OAuth realm=\'http://sp.example.com/\', error=\'expired_token\', ' +
|
108
108
|
'error_description=\'The access token has expired.\''
|
109
109
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
110
|
-
parameters['realm'].
|
111
|
-
parameters['error'].
|
112
|
-
parameters['error_description'].
|
110
|
+
expect(parameters['realm']).to eq 'http://sp.example.com/'
|
111
|
+
expect(parameters['error']).to eq 'expired_token'
|
112
|
+
expect(parameters['error_description']).to eq 'The access token has expired.'
|
113
113
|
end
|
114
114
|
|
115
115
|
it 'should liberally handle auth-params with token strings' do
|
@@ -117,9 +117,9 @@ describe Signet::OAuth2 do
|
|
117
117
|
'OAuth realm="http://sp.example.com/", error=expired_token, ' +
|
118
118
|
'error_description="The access token has expired."'
|
119
119
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
120
|
-
parameters['realm'].
|
121
|
-
parameters['error'].
|
122
|
-
parameters['error_description'].
|
120
|
+
expect(parameters['realm']).to eq 'http://sp.example.com/'
|
121
|
+
expect(parameters['error']).to eq 'expired_token'
|
122
|
+
expect(parameters['error_description']).to eq 'The access token has expired.'
|
123
123
|
end
|
124
124
|
|
125
125
|
it 'should liberally handle out-of-order auth-params' do
|
@@ -127,64 +127,74 @@ describe Signet::OAuth2 do
|
|
127
127
|
'OAuth error_description=\'The access token has expired.\', ' +
|
128
128
|
'error=\'expired_token\', realm=\'http://sp.example.com/\''
|
129
129
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
130
|
-
parameters['realm'].
|
131
|
-
parameters['error'].
|
132
|
-
parameters['error_description'].
|
130
|
+
expect(parameters['realm']).to eq 'http://sp.example.com/'
|
131
|
+
expect(parameters['error']).to eq 'expired_token'
|
132
|
+
expect(parameters['error_description']).to eq 'The access token has expired.'
|
133
133
|
end
|
134
134
|
|
135
135
|
it 'should not allow unquoted strings that do not match tchar' do
|
136
|
-
(lambda do
|
136
|
+
expect(lambda do
|
137
137
|
Signet::OAuth2.parse_www_authenticate_header(
|
138
138
|
'OAuth realm=http://sp.example.com/, error=expired_token, ' +
|
139
139
|
'error_description="The access token has expired."'
|
140
140
|
)
|
141
|
-
end).
|
141
|
+
end).to raise_error(Signet::ParseError)
|
142
142
|
end
|
143
143
|
|
144
144
|
it 'should not parse non-OAuth challenges' do
|
145
|
-
(lambda do
|
145
|
+
expect(lambda do
|
146
146
|
Signet::OAuth2.parse_www_authenticate_header(
|
147
147
|
'AuthSub realm="https://www.google.com/accounts/AuthSubRequest"'
|
148
148
|
)
|
149
|
-
end).
|
149
|
+
end).to raise_error(Signet::ParseError)
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
153
|
describe 'when generating a Basic Authorization header' do
|
154
154
|
it 'should correctly handle client ID and password pairs' do
|
155
155
|
# Example from OAuth 2 spec
|
156
|
-
Signet::OAuth2.generate_basic_authorization_header(
|
156
|
+
expect(Signet::OAuth2.generate_basic_authorization_header(
|
157
157
|
's6BhdRkqt3', 'gX1fBat3bV'
|
158
|
-
).
|
158
|
+
)).to eq 'Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW'
|
159
159
|
end
|
160
160
|
|
161
161
|
it 'should correctly encode using the alogrithm given in RFC 2617' do
|
162
162
|
# Example from RFC 2617
|
163
|
-
Signet::OAuth2.generate_basic_authorization_header(
|
163
|
+
expect(Signet::OAuth2.generate_basic_authorization_header(
|
164
164
|
'Aladdin', 'open sesame'
|
165
|
-
).
|
165
|
+
)).to eq 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
169
169
|
describe 'when parsing a token response body' do
|
170
|
+
|
170
171
|
it 'should correctly handle just an access token' do
|
171
|
-
Signet::OAuth2.
|
172
|
-
'{"access_token": "12345"}'
|
173
|
-
|
172
|
+
expect(Signet::OAuth2.parse_credentials(
|
173
|
+
'{"access_token": "12345"}',
|
174
|
+
'application/json; charset=utf-8'
|
175
|
+
)).to eq ({"access_token" => "12345"})
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should handle form encoded responses' do
|
179
|
+
expect(Signet::OAuth2.parse_credentials(
|
180
|
+
'access_token=12345&expires=1000',
|
181
|
+
'application/x-www-form-urlencoded; charset=utf-8'
|
182
|
+
)).to eq({"access_token" => "12345", "expires" => "1000" })
|
174
183
|
end
|
175
184
|
|
176
185
|
it 'should raise an error for an invalid body' do
|
177
|
-
(lambda do
|
178
|
-
Signet::OAuth2.
|
179
|
-
'This is not JSON.'
|
186
|
+
expect(lambda do
|
187
|
+
Signet::OAuth2.parse_credentials(
|
188
|
+
'This is not JSON.',
|
189
|
+
'application/json'
|
180
190
|
)
|
181
|
-
end).
|
191
|
+
end).to raise_error(MultiJson::DecodeError)
|
182
192
|
end
|
183
193
|
|
184
194
|
it 'should raise an error for a bogus body' do
|
185
|
-
(lambda do
|
186
|
-
Signet::OAuth2.
|
187
|
-
end).
|
195
|
+
expect(lambda do
|
196
|
+
Signet::OAuth2.parse_credentials(:bogus, 'application/json')
|
197
|
+
end).to raise_error(TypeError)
|
188
198
|
end
|
189
199
|
end
|
190
200
|
end
|
data/spec/signet_spec.rb
CHANGED
@@ -26,59 +26,59 @@ describe Signet do
|
|
26
26
|
parameters = Signet.parse_auth_param_list(
|
27
27
|
'a="1, 2" , b="3,4",c="5 , 6" ,d="7 ,8"'
|
28
28
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
29
|
-
parameters['a'].
|
30
|
-
parameters['b'].
|
31
|
-
parameters['c'].
|
32
|
-
parameters['d'].
|
29
|
+
expect(parameters['a']).to eq '1, 2'
|
30
|
+
expect(parameters['b']).to eq '3,4'
|
31
|
+
expect(parameters['c']).to eq '5 , 6'
|
32
|
+
expect(parameters['d']).to eq '7 ,8'
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'should correctly handle backslash-escaped pairs' do
|
36
36
|
parameters = Signet.parse_auth_param_list(
|
37
37
|
'token="\t\o\k\e\n" sigalg="\s\i\g\a\l\g" data="\d\a\t\a"'
|
38
38
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
39
|
-
parameters['token'].
|
40
|
-
parameters['sigalg'].
|
41
|
-
parameters['data'].
|
39
|
+
expect(parameters['token']).to eq 'token'
|
40
|
+
expect(parameters['sigalg']).to eq 'sigalg'
|
41
|
+
expect(parameters['data']).to eq 'data'
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'should liberally handle space-separated auth-param lists' do
|
45
45
|
parameters = Signet.parse_auth_param_list(
|
46
46
|
'token="token" sigalg="sigalg" data="data" sig="sig"'
|
47
47
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
48
|
-
parameters['token'].
|
49
|
-
parameters['sigalg'].
|
50
|
-
parameters['data'].
|
51
|
-
parameters['sig'].
|
48
|
+
expect(parameters['token']).to eq 'token'
|
49
|
+
expect(parameters['sigalg']).to eq 'sigalg'
|
50
|
+
expect(parameters['data']).to eq 'data'
|
51
|
+
expect(parameters['sig']).to eq 'sig'
|
52
52
|
end
|
53
53
|
|
54
54
|
it 'should liberally handle single-quoted auth-param lists' do
|
55
55
|
parameters = Signet.parse_auth_param_list(
|
56
56
|
'token=\'token\' sigalg=\'sigalg\' data=\'data\' sig=\'sig\''
|
57
57
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
58
|
-
parameters['token'].
|
59
|
-
parameters['sigalg'].
|
60
|
-
parameters['data'].
|
61
|
-
parameters['sig'].
|
58
|
+
expect(parameters['token']).to eq 'token'
|
59
|
+
expect(parameters['sigalg']).to eq 'sigalg'
|
60
|
+
expect(parameters['data']).to eq 'data'
|
61
|
+
expect(parameters['sig']).to eq 'sig'
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'should liberally handle unquoted auth-param lists' do
|
65
65
|
parameters = Signet.parse_auth_param_list(
|
66
66
|
'token=token sigalg=sigalg data=data sig=sig'
|
67
67
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
68
|
-
parameters['token'].
|
69
|
-
parameters['sigalg'].
|
70
|
-
parameters['data'].
|
71
|
-
parameters['sig'].
|
68
|
+
expect(parameters['token']).to eq 'token'
|
69
|
+
expect(parameters['sigalg']).to eq 'sigalg'
|
70
|
+
expect(parameters['data']).to eq 'data'
|
71
|
+
expect(parameters['sig']).to eq 'sig'
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'should liberally handle auth-param lists with empty sections' do
|
75
75
|
parameters = Signet.parse_auth_param_list(
|
76
76
|
'token=token, , sigalg=sigalg,, data=data, sig=sig'
|
77
77
|
).inject({}) { |h,(k,v)| h[k]=v; h }
|
78
|
-
parameters['token'].
|
79
|
-
parameters['sigalg'].
|
80
|
-
parameters['data'].
|
81
|
-
parameters['sig'].
|
78
|
+
expect(parameters['token']).to eq 'token'
|
79
|
+
expect(parameters['sigalg']).to eq 'sigalg'
|
80
|
+
expect(parameters['data']).to eq 'data'
|
81
|
+
expect(parameters['sig']).to eq 'sig'
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
data/spec/spec_helper.rb
CHANGED
data/tasks/gem.rake
CHANGED
@@ -1,62 +1,10 @@
|
|
1
1
|
require "rubygems/package_task"
|
2
2
|
|
3
3
|
namespace :gem do
|
4
|
-
GEM_SPEC = Gem::Specification.new do |s|
|
5
|
-
unless s.respond_to?(:add_development_dependency)
|
6
|
-
puts "The gem spec requires a newer version of RubyGems."
|
7
|
-
exit(1)
|
8
|
-
end
|
9
|
-
|
10
|
-
s.name = PKG_NAME
|
11
|
-
s.version = PKG_VERSION
|
12
|
-
s.author = PKG_AUTHOR
|
13
|
-
s.email = PKG_AUTHOR_EMAIL
|
14
|
-
s.homepage = PKG_HOMEPAGE
|
15
|
-
s.summary = PKG_SUMMARY
|
16
|
-
s.description = PKG_DESCRIPTION
|
17
|
-
|
18
|
-
s.files = PKG_FILES.to_a
|
19
|
-
|
20
|
-
s.has_rdoc = true
|
21
|
-
s.extra_rdoc_files = %w( README.md )
|
22
|
-
s.rdoc_options.concat ["--main", "README.md"]
|
23
|
-
|
24
|
-
s.add_runtime_dependency("addressable", ">= 2.2.3")
|
25
|
-
s.add_runtime_dependency("faraday", ">= 0.9.0.rc5")
|
26
|
-
s.add_runtime_dependency("multi_json", ">= 1.0.0")
|
27
|
-
s.add_runtime_dependency("jwt", ">= 0.1.5")
|
28
|
-
|
29
|
-
s.add_development_dependency("rake", ">= 0.9.0")
|
30
|
-
s.add_development_dependency("rspec", ">= 2.11.0")
|
31
|
-
s.add_development_dependency("launchy", ">= 2.1.1")
|
32
|
-
|
33
|
-
s.require_path = "lib"
|
34
|
-
end
|
35
|
-
|
36
|
-
Gem::PackageTask.new(GEM_SPEC) do |p|
|
37
|
-
p.gem_spec = GEM_SPEC
|
38
|
-
p.need_tar = true
|
39
|
-
p.need_zip = true
|
40
|
-
end
|
41
|
-
|
42
|
-
desc "Generates .gemspec file"
|
43
|
-
task :gemspec do
|
44
|
-
spec_string = GEM_SPEC.to_ruby
|
45
|
-
|
46
|
-
begin
|
47
|
-
Thread.new { eval("$SAFE = 3\n#{spec_string}", binding) }.join
|
48
|
-
rescue
|
49
|
-
abort "unsafe gemspec: #{$!}"
|
50
|
-
else
|
51
|
-
File.open("#{GEM_SPEC.name}.gemspec", 'w') do |file|
|
52
|
-
file.write spec_string
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
4
|
|
57
|
-
desc "
|
58
|
-
task :
|
59
|
-
|
5
|
+
desc "Build the gem"
|
6
|
+
task :build do
|
7
|
+
system "gem build signet.gemspec"
|
60
8
|
end
|
61
9
|
|
62
10
|
desc "Install the gem"
|
data/tasks/spec.rake
CHANGED
@@ -4,33 +4,15 @@ require 'rake/clean'
|
|
4
4
|
CLOBBER.include('coverage', 'specdoc')
|
5
5
|
|
6
6
|
namespace :spec do
|
7
|
-
RSpec::Core::RakeTask.new(:rcov) do |t|
|
8
|
-
t.pattern = FileList['spec/**/*_spec.rb']
|
9
|
-
t.rspec_opts = ['--color', '--format', 'documentation']
|
10
|
-
|
11
|
-
t.rcov = RCOV_ENABLED
|
12
|
-
t.rcov_opts = [
|
13
|
-
'--exclude', 'lib\\/compat',
|
14
|
-
'--exclude', 'spec',
|
15
|
-
'--exclude', '\\.rvm\\/gems',
|
16
|
-
'--exclude', '1\\.8\\/gems',
|
17
|
-
'--exclude', '1\\.9\\/gems',
|
18
|
-
'--exclude', '\\.rvm',
|
19
|
-
'--exclude', '\\/Library\\/Ruby',
|
20
|
-
'--exclude', 'addressable\\/idna' # environment dependant
|
21
|
-
]
|
22
|
-
end
|
23
7
|
|
24
8
|
RSpec::Core::RakeTask.new(:normal) do |t|
|
25
9
|
t.pattern = FileList['spec/**/*_spec.rb'].exclude(/compat/)
|
26
10
|
t.rspec_opts = ['--color', '--format', 'documentation']
|
27
|
-
t.rcov = false
|
28
11
|
end
|
29
12
|
|
30
13
|
RSpec::Core::RakeTask.new(:all) do |t|
|
31
14
|
t.pattern = FileList['spec/**/*_spec.rb']
|
32
15
|
t.rspec_opts = ['--color', '--format', 'documentation']
|
33
|
-
t.rcov = false
|
34
16
|
end
|
35
17
|
|
36
18
|
desc "Generate HTML Specdocs for all specs"
|
@@ -46,13 +28,6 @@ namespace :spec do
|
|
46
28
|
t.fail_on_error = false
|
47
29
|
end
|
48
30
|
|
49
|
-
namespace :rcov do
|
50
|
-
desc "Browse the code coverage report."
|
51
|
-
task :browse => "spec:rcov" do
|
52
|
-
require "launchy"
|
53
|
-
Launchy::Browser.run("coverage/index.html")
|
54
|
-
end
|
55
|
-
end
|
56
31
|
end
|
57
32
|
|
58
33
|
desc "Alias to spec:normal"
|