signet 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- gem 'faraday', '~> 0.7.0'
15
+ gem 'faraday', '~> 0.8.1'
16
16
  require 'faraday'
17
17
  require 'faraday/utils'
18
18
 
@@ -657,6 +657,7 @@ module Signet
657
657
  raise ArgumentError, 'Missing token endpoint URI.'
658
658
  end
659
659
 
660
+ options[:connection] ||= Faraday.default_connection
660
661
  method = 'POST'
661
662
  parameters = {"grant_type" => self.grant_type}
662
663
  case self.grant_type
@@ -682,8 +683,12 @@ module Signet
682
683
  ['Cache-Control', 'no-store'],
683
684
  ['Content-Type', 'application/x-www-form-urlencoded']
684
685
  ]
685
- return Faraday::Request.create(method.to_s.downcase.to_sym) do |req|
686
- req.url(Addressable::URI.parse(self.token_credential_uri))
686
+ return options[:connection].build_request(
687
+ method.to_s.downcase.to_sym
688
+ ) do |req|
689
+ req.url(Addressable::URI.parse(
690
+ self.token_credential_uri
691
+ ).normalize.to_s)
687
692
  req.headers = Faraday::Utils::Headers.new(headers)
688
693
  req.body = Addressable::URI.form_encode(parameters)
689
694
  end
@@ -693,6 +698,7 @@ module Signet
693
698
  options[:connection] ||= Faraday.default_connection
694
699
  request = self.generate_access_token_request(options)
695
700
  request_env = request.to_env(options[:connection])
701
+ request_env[:request] ||= request
696
702
  response = options[:connection].app.call(request_env)
697
703
  if response.status.to_i == 200
698
704
  return ::Signet::OAuth2.parse_json_credentials(response.body)
@@ -756,6 +762,7 @@ module Signet
756
762
  options = {
757
763
  :realm => nil
758
764
  }.merge(options)
765
+
759
766
  if options[:request].kind_of?(Faraday::Request)
760
767
  request = options[:request]
761
768
  else
@@ -781,8 +788,8 @@ module Signet
781
788
  end
782
789
  end
783
790
  method = method.to_s.downcase.to_sym
784
- request = Faraday::Request.create(method.to_s.downcase.to_sym) do |req|
785
- req.url(Addressable::URI.parse(uri))
791
+ request = options[:connection].build_request(method.to_s.downcase.to_sym) do |req|
792
+ req.url(Addressable::URI.parse(uri).normalize.to_s)
786
793
  req.headers = Faraday::Utils::Headers.new(headers)
787
794
  req.body = body
788
795
  end
@@ -840,6 +847,7 @@ module Signet
840
847
  options[:connection] ||= Faraday.default_connection
841
848
  request = self.generate_authenticated_request(options)
842
849
  request_env = request.to_env(options[:connection])
850
+ request_env[:request] ||= request
843
851
  response = options[:connection].app.call(request_env)
844
852
  if response.status.to_i == 401
845
853
  # When accessing a protected resource, we only want to raise an
@@ -17,8 +17,8 @@ unless defined? Signet::VERSION
17
17
  module Signet
18
18
  module VERSION
19
19
  MAJOR = 0
20
- MINOR = 3
21
- TINY = 4
20
+ MINOR = 4
21
+ TINY = 0
22
22
 
23
23
  STRING = [MAJOR, MINOR, TINY].join('.')
24
24
  end
@@ -12,12 +12,18 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ spec_dir = File.expand_path(File.join(File.dirname(__FILE__), "../.."))
16
+ $:.unshift(spec_dir)
17
+ $:.uniq!
18
+
15
19
  require 'spec_helper'
16
20
 
17
21
  require 'signet/oauth_1/client'
18
22
  require 'addressable/uri'
19
23
  require 'stringio'
20
24
 
25
+ conn = Faraday.default_connection
26
+
21
27
  def merge_body(chunked_body)
22
28
  if chunked_body == nil
23
29
  raise ArgumentError, "Expected chunked body, got nil."
@@ -518,13 +524,11 @@ describe Signet::OAuth1::Client, 'configured' do
518
524
 
519
525
  it 'should not raise an error if a request is ' +
520
526
  'provided without a connection' do
521
- (lambda do
522
- @client.generate_authenticated_request(
523
- :request => Faraday::Request.new(:get) do |req|
524
- req.url('http://www.example.com/')
525
- end
526
- )
527
- end).should_not raise_error(ArgumentError)
527
+ request = @client.generate_authenticated_request(
528
+ :request => conn.build_request(:get) do |req|
529
+ req.url('http://www.example.com/')
530
+ end
531
+ )
528
532
  end
529
533
 
530
534
  it 'should raise an error if no URI is provided' do
@@ -633,7 +637,9 @@ describe Signet::OAuth1::Client, 'configured' do
633
637
  )
634
638
  signed_request.method.should == :get
635
639
  signed_request.path.should ===
636
- 'https://photos.example.net/photos?file=vacation.jpg&size=original'
640
+ 'https://photos.example.net/photos'
641
+ signed_request.params.should ==
642
+ {"file"=>"vacation.jpg", "size"=>"original"}
637
643
  authorization_header = signed_request.headers['Authorization']
638
644
  signed_request.body.should == ''
639
645
  parameters = ::Signet::OAuth1.parse_authorization_header(
@@ -696,9 +702,13 @@ describe Signet::OAuth1::Client, 'configured' do
696
702
  it 'should correctly get the protected resource' do
697
703
  # Repeat this because signatures change from test to test
698
704
  10.times do
699
- original_request = Faraday::Request.create(:get) do |req|
700
- req.url(Addressable::URI.parse('https://photos.example.net/photos?file=vacation.jpg&size=original'))
701
- req.headers = Faraday::Utils::Headers.new([['Host', 'photos.example.net']])
705
+ original_request = conn.build_request(:get) do |req|
706
+ req.url(
707
+ 'https://photos.example.net/photos?file=vacation.jpg&size=original'
708
+ )
709
+ req.headers = Faraday::Utils::Headers.new(
710
+ [['Host', 'photos.example.net']]
711
+ )
702
712
  req.body = ''
703
713
  end
704
714
 
@@ -711,7 +721,9 @@ describe Signet::OAuth1::Client, 'configured' do
711
721
 
712
722
  signed_request.method.should == :get
713
723
  signed_request.path.should ===
714
- 'https://photos.example.net/photos?file=vacation.jpg&size=original'
724
+ 'https://photos.example.net/photos'
725
+ signed_request.params.should ===
726
+ {"file"=>"vacation.jpg", "size"=>"original"}
715
727
  authorization_header = signed_request.headers['Authorization']
716
728
  signed_request.body.should == ''
717
729
  parameters = ::Signet::OAuth1.parse_authorization_header(
@@ -734,8 +746,8 @@ describe Signet::OAuth1::Client, 'configured' do
734
746
  it 'should correctly post the protected resource' do
735
747
  # Repeat this because signatures change from test to test
736
748
  10.times do
737
- original_request = Faraday::Request.create(:post) do |req|
738
- req.url(Addressable::URI.parse('https://photos.example.net/photos'))
749
+ original_request = conn.build_request(:post) do |req|
750
+ req.url('https://photos.example.net/photos')
739
751
  req.headers = Faraday::Utils::Headers.new([
740
752
  ['Host', 'photos.example.net'],
741
753
  ['Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'],
@@ -12,6 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ spec_dir = File.expand_path(File.join(File.dirname(__FILE__), "../.."))
16
+ $:.unshift(spec_dir)
17
+ $:.uniq!
18
+
15
19
  require 'spec_helper'
16
20
 
17
21
  require 'signet/oauth_1/credential'
@@ -0,0 +1,846 @@
1
+ # Copyright (C) 2011 The Yakima Herald-Republic.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ spec_dir = File.expand_path(File.join(File.dirname(__FILE__), "../.."))
16
+ $:.unshift(spec_dir)
17
+ $:.uniq!
18
+
19
+ require 'spec_helper'
20
+
21
+ require 'signet/oauth_1/server'
22
+ require 'signet/oauth_1/client'
23
+ require 'addressable/uri'
24
+ require 'stringio'
25
+
26
+ def merge_body(chunked_body)
27
+ merged_body = StringIO.new
28
+ chunked_body.each do |chunk|
29
+ merged_body.write(chunk)
30
+ end
31
+ return merged_body.string
32
+ end
33
+
34
+ def make_oauth_signature_header(real_headers={})
35
+ [oauth_headers({'oauth_signature' => 'oauth_signature'}.merge(real_headers))]
36
+ end
37
+ def make_oauth_token_header(real_headers={})
38
+ [oauth_headers({'oauth_token' => 'oauth_token'}.merge(real_headers))]
39
+ end
40
+
41
+ def oauth_headers(real_headers={})
42
+ headers = {}
43
+ %w[oauth_consumer_key oauth_timestamp oauth_nonce].each do |key|
44
+ headers[key] = key
45
+ end
46
+ headers['oauth_signature_method'] = 'HMAC-SHA1'
47
+ headers['oauth_version'] = '1.0'
48
+ headers.merge!(real_headers)
49
+ ['Authorization', ::Signet::OAuth1.generate_authorization_header(headers, nil)]
50
+ end
51
+
52
+ def make_temporary_credential_request(client, callback=nil, uri=nil, realm=nil)
53
+ client.callback = callback if callback
54
+ client.temporary_credential_uri = uri || 'http://photos.example.net/initiate'
55
+ client.generate_temporary_credential_request(:realm=>realm)
56
+ end
57
+
58
+ def make_token_credential_request(client, verifier=nil, realm=nil, uri=nil)
59
+ client.token_credential_uri = uri || 'http://photos.example.net/token'
60
+ client.generate_token_credential_request(:verifier=>verifier || '12345',
61
+ :realm=>realm
62
+ )
63
+ end
64
+
65
+ def make_resource_request(client, real_request={}, realm=nil)
66
+
67
+ client.generate_authenticated_request(
68
+ :method => real_request[:method] || 'GET',
69
+ :uri => real_request[:uri] || 'http://photos.example.net/photos',
70
+ :body=> real_request[:body],
71
+ :headers=>real_request[:headers],
72
+ :realm=>realm
73
+ )
74
+ end
75
+
76
+
77
+ describe Signet::OAuth1::Server, 'unconfigured' do
78
+ before do
79
+ @server = Signet::OAuth1::Server.new
80
+ end
81
+ it 'should not have a client_credential Proc' do
82
+ @server.client_credential.should == nil
83
+ end
84
+ it 'should not have a token_credential Proc' do
85
+ @server.token_credential.should == nil
86
+ end
87
+ it 'should not have a nonce_timestamp Proc' do
88
+ @server.nonce_timestamp.should == nil
89
+ end
90
+ it 'should not have a verifier Proc' do
91
+ @server.verifier.should == nil
92
+ end
93
+ end
94
+
95
+
96
+ describe Signet::OAuth1::Server, 'configured' do
97
+ before do
98
+ @server = Signet::OAuth1::Server.new
99
+ @client_credential_key = 'dpf43f3p2l4k3l03'
100
+ @client_credential_secret = 'kd94hf93k423kf44'
101
+ @token_credential_key = 'nnch734d00sl2jdk'
102
+ @token_credential_secret = 'pfkkdhi9sl3r4s00'
103
+ @temporary_credential_key = 'hh5s93j4hdidpola'
104
+ @temporary_credential_secret = 'hdhd0244k9j7ao03'
105
+ @verifier = 'hfdp7dh39dks9884'
106
+
107
+ @server.client_credential =
108
+ lambda do |x|
109
+ x.nil? ? nil : Signet::OAuth1::Credential.new(@client_credential_key,
110
+ @client_credential_secret)
111
+ end
112
+ @server.token_credential =
113
+ lambda do |x|
114
+ x.nil? ? nil : Signet::OAuth1::Credential.new(@token_credential_key,
115
+ @token_credential_secret)
116
+ end
117
+ @server.temporary_credential =
118
+ lambda do |x|
119
+ x.nil? ? nil : Signet::OAuth1::Credential.new(@temporary_credential_key,
120
+ @temporary_credential_secret)
121
+ end
122
+ @server.nonce_timestamp =
123
+ lambda do |nonce, timestamp|
124
+ !(nonce.nil? && timestamp.nil?)
125
+ end
126
+ @server.verifier = lambda { |x| x == @verifier }
127
+ end
128
+
129
+ it 'should raise an error if the client credential Proc is not set' do
130
+ @server.client_credential = nil
131
+ (lambda do
132
+ @server.authenticate_resource_request
133
+ end).should raise_error(ArgumentError)
134
+ end
135
+
136
+ it "should raise an error if the token credential Proc is not set" do
137
+ @server.token_credential = nil
138
+ (lambda do
139
+ @server.authenticate_resource_request
140
+ end).should raise_error(ArgumentError)
141
+ end
142
+
143
+ it "should raise an error if the temporary token credential Proc is not set" do
144
+ @server.temporary_credential = nil
145
+ (lambda do
146
+ @server.authenticate_token_credential_request
147
+ end).should raise_error(ArgumentError)
148
+ end
149
+
150
+ it "should raise an error if the verifier Proc is not set for a token request" do
151
+ @server.verifier = nil
152
+ (lambda do
153
+ @server.authenticate_token_credential_request
154
+ end).should raise_error(ArgumentError)
155
+ end
156
+
157
+ it 'should raise an error if no request is provided' do
158
+ (lambda do
159
+ @server.authenticate_resource_request
160
+ end).should raise_error(ArgumentError)
161
+ end
162
+
163
+ it 'should raise an error if a bogus request is provided' do
164
+ (lambda do
165
+ @server.authenticate_resource_request(
166
+ :request => []
167
+ )
168
+ end).should raise_error(ArgumentError)
169
+ end
170
+
171
+ it 'should raise an error if no Authentication header is provided' do
172
+ (lambda do
173
+ @server.authenticate_resource_request(
174
+ :method => 'GET',
175
+ :uri => 'https://photos.example.net/photos',
176
+ :headers => [['Authorization', '']],
177
+ :body => ''
178
+ )
179
+ end).should raise_error(Signet::MalformedAuthorizationError)
180
+ end
181
+
182
+ it 'should raise an error if no URI is provided' do
183
+ (lambda do
184
+ @server.authenticate_resource_request(
185
+ :method => 'GET',
186
+ :headers => [],
187
+ :body => ''
188
+ )
189
+ end).should raise_error(ArgumentError)
190
+ end
191
+
192
+ it 'should reject a request with the wrong signature method' do
193
+ bad_method = 'FOO'
194
+ (lambda do
195
+ @server.authenticate_resource_request(
196
+ :method => 'GET',
197
+ :uri => 'http://photos.example.net/photos',
198
+ :headers=>make_oauth_token_header({'oauth_signature_method'=>bad_method})
199
+ )
200
+ end).should raise_error(NotImplementedError,
201
+ "Unsupported signature method: #{bad_method}"
202
+ )
203
+ end
204
+
205
+
206
+ describe 'calling find_temporary_credential' do
207
+ it 'should return a Signet credential if the Proc provides one' do
208
+ @server.temporary_credential =
209
+ lambda do |x|
210
+ x.nil? ? nil : Signet::OAuth1::Credential.new(
211
+ @temporary_credential_key, @temporary_credential_secret
212
+ )
213
+ end
214
+ @server.find_temporary_credential(@temporary_credential_key).should ==
215
+ Signet::OAuth1::Credential.new(@temporary_credential_key,
216
+ @temporary_credential_secret)
217
+ end
218
+ it 'should return a Signet credential if the Proc provides a key/secret pair' do
219
+ @server.temporary_credential =
220
+ lambda do |x|
221
+ {:key=>@temporary_credential_key, :secret=>@temporary_credential_secret}
222
+ end
223
+ @server.find_temporary_credential(@temporary_credential_key).should ==
224
+ Signet::OAuth1::Credential.new(@temporary_credential_key,
225
+ @temporary_credential_secret)
226
+ end
227
+ it 'should return a Signet credential if the Proc provides ' +
228
+ 'a key/secret Enumerable' do
229
+ @server.temporary_credential =
230
+ lambda do |x|
231
+ [@temporary_credential_key, @temporary_credential_secret]
232
+ end
233
+ @server.find_temporary_credential(@temporary_credential_key).should ==
234
+ Signet::OAuth1::Credential.new(@temporary_credential_key,
235
+ @temporary_credential_secret
236
+ )
237
+ end
238
+
239
+ it 'should return nil if the Proc does not provide a usable response' do
240
+ @server.temporary_credential = lambda {|x| nil }
241
+ @server.find_temporary_credential(@temporary_credential_key).should == nil
242
+ end
243
+ end
244
+
245
+
246
+ describe 'calling find_client_credential' do
247
+ it 'should return a Signet credential if the Proc provides one' do
248
+ @server.client_credential =
249
+ lambda do |x|
250
+ x.nil? ? nil : Signet::OAuth1::Credential.new(@client_credential_key,
251
+ @client_credential_secret)
252
+ end
253
+ @server.find_client_credential(@client_credential_key).should ==
254
+ Signet::OAuth1::Credential.new(@client_credential_key,
255
+ @client_credential_secret)
256
+ end
257
+ it 'should return a Signet credential if the Proc provides a key/secret pair' do
258
+ @server.client_credential =
259
+ lambda do |x|
260
+ {:key=>@client_credential_key, :secret=>@client_credential_secret}
261
+ end
262
+ @server.find_client_credential(@client_credential_key).should ==
263
+ Signet::OAuth1::Credential.new(@client_credential_key,
264
+ @client_credential_secret)
265
+ end
266
+ it 'should return a Signet credential if the Proc provides ' +
267
+ 'a key/secret Enumerable' do
268
+ @server.client_credential =
269
+ lambda do |x|
270
+ [@client_credential_key, @client_credential_secret]
271
+ end
272
+ @server.find_client_credential(@client_credential_key).should ==
273
+ Signet::OAuth1::Credential.new(@client_credential_key,
274
+ @client_credential_secret)
275
+ end
276
+
277
+ it 'should return nil if the Proc does not provide a usable response' do
278
+ @server.client_credential = lambda {|x| nil }
279
+ @server.find_client_credential(@client_credential_key).should == nil
280
+ end
281
+ end
282
+
283
+
284
+ describe 'calling find_token_credential' do
285
+ it 'should return a Signet credential if the Proc provides one' do
286
+ @server.token_credential =
287
+ lambda do |x|
288
+ x.nil? ? nil : Signet::OAuth1::Credential.new(@token_credential_key,
289
+ @token_credential_secret)
290
+ end
291
+ @server.find_token_credential(@token_credential_key).should ==
292
+ Signet::OAuth1::Credential.new(@token_credential_key,
293
+ @token_credential_secret)
294
+ end
295
+
296
+ it 'should return a Signet credential if the Proc provides a key/secret pair' do
297
+ @server.token_credential =
298
+ lambda do |x|
299
+ {:key=>@token_credential_key, :secret=>@token_credential_secret}
300
+ end
301
+ @server.find_token_credential(@token_credential_key).should ==
302
+ Signet::OAuth1::Credential.new(@token_credential_key,
303
+ @token_credential_secret)
304
+ end
305
+
306
+ it 'should return a Signet credential if the Proc provides ' +
307
+ 'a key/secret Enumerable' do
308
+ @server.token_credential =
309
+ lambda do |x|
310
+ [@token_credential_key, @token_credential_secret]
311
+ end
312
+ @server.find_token_credential(@token_credential_key).should ==
313
+ Signet::OAuth1::Credential.new(@token_credential_key,
314
+ @token_credential_secret)
315
+ end
316
+
317
+ it 'should return nil if the Proc does not provide a usable response' do
318
+ @server.token_credential = lambda {|x| nil }
319
+ @server.find_token_credential(@token_credential_key).should == nil
320
+ end
321
+ end
322
+
323
+
324
+ describe 'calling find_verifier' do
325
+ it 'should return false if server verifier returns false' do
326
+ @server.verifier = lambda {|x| false }
327
+ @server.find_verifier(@verifier).should == false
328
+ end
329
+ it 'should return false if server verifier returns nil' do
330
+ @server.verifier = lambda {|x| nil }
331
+ @server.find_verifier(@verifier).should == false
332
+ end
333
+ it 'should return true if server verifier returns a random object' do
334
+ @server.verifier = lambda {|x| x.succ}
335
+ @server.find_verifier(@verifier).should == true
336
+ end
337
+ end
338
+
339
+ describe 'calling validate_nonce_timestamp' do
340
+ it 'should return false if nonce_timestamp Proc returns false' do
341
+ @server.nonce_timestamp = lambda {|n,t| false}
342
+ @server.validate_nonce_timestamp('nonce', 'timestamp'). should == false
343
+ end
344
+ it 'should return false if nonce_timestamp Proc returns nil' do
345
+ @server.nonce_timestamp = lambda {|n,t| nil}
346
+ @server.validate_nonce_timestamp('nonce', 'timestamp'). should == false
347
+ end
348
+ it 'should return true if nonce_timestamp Proc returns a random object' do
349
+ @server.nonce_timestamp = lambda {|n,t| n+t.to_s}
350
+ @server.validate_nonce_timestamp('nonce', 'timestamp'). should == true
351
+ end
352
+ end
353
+
354
+
355
+ describe 'expecting a request for a temporary credential' do
356
+ before do
357
+ @client = Signet::OAuth1::Client.new(
358
+ :client_credential_key=>@client_credential_key,
359
+ :client_credential_secret=>@client_credential_secret,
360
+ :temporary_credential_uri=>
361
+ 'http://photos.example.net/initiate')
362
+ end
363
+
364
+ it 'should raise an error if the client credential Proc is not set' do
365
+ @server.client_credential = nil
366
+ (lambda do
367
+ @server.authenticate_temporary_credential_request(
368
+ :request=>make_temporary_credential_request(@client)
369
+ )
370
+ end).should raise_error(ArgumentError)
371
+ end
372
+ it 'should reject an malformed request' do
373
+ bad_request = make_temporary_credential_request(@client, nil, 'https://photos.example.net/photos')
374
+ bad_request.headers['Authorization'].gsub!(/(OAuth)(.+)/, "#{$1}")
375
+ (lambda do
376
+ @server.authenticate_temporary_credential_request(
377
+ :request=>bad_request
378
+ )
379
+ end).should raise_error(Signet::MalformedAuthorizationError)
380
+ end
381
+
382
+ it 'should call a user-supplied Proc to validate a nonce/timestamp pair' do
383
+ nonce_callback = mock('nonce')
384
+ nonce_callback.should_receive(:call).once.with(an_instance_of(String),
385
+ an_instance_of(String)
386
+ ).and_return(true)
387
+
388
+ @server.nonce_timestamp = nonce_callback
389
+ @server.authenticate_temporary_credential_request(
390
+ :request=>make_temporary_credential_request(@client)
391
+ )
392
+ end
393
+
394
+ it "should return 'oob' for a valid request without an oauth_callback" do
395
+ bad_request = make_temporary_credential_request(@client)
396
+ @server.authenticate_temporary_credential_request(
397
+ :request=>bad_request
398
+ ).should == 'oob'
399
+ end
400
+ it 'should return the oauth_callback for a valid request ' +
401
+ 'with an oauth_callback' do
402
+ callback = 'http://printer.example.com/ready'
403
+ @server.authenticate_temporary_credential_request(
404
+ :request=>make_temporary_credential_request(@client, callback)
405
+ ).should == callback
406
+ end
407
+ it 'should return false for an unauthenticated request' do
408
+ bad_request = make_temporary_credential_request(@client)
409
+ bad_request.headers["Authorization"].gsub!(/oauth_signature=\".+\"/,
410
+ "oauth_signature=\"foobar\"")
411
+ @server.authenticate_temporary_credential_request(
412
+ :request=>bad_request
413
+ ).should == false
414
+ end
415
+ it 'should return nil from #request_realm if no realm is provided' do
416
+ req = make_temporary_credential_request(@client)
417
+ @server.request_realm(
418
+ :request=>req
419
+ ).should == nil
420
+ end
421
+
422
+ describe 'with a Realm provided' do
423
+ it 'should return the realm from #request_realm' do
424
+ req = make_temporary_credential_request(@client, nil, nil, 'Photos')
425
+ @server.request_realm(
426
+ :request=>req
427
+ ).should == 'Photos'
428
+ end
429
+ it 'should return "oob" with a valid request without an oauth_callback' do
430
+ req = make_temporary_credential_request(@client, nil, nil, 'Photos')
431
+ @server.authenticate_temporary_credential_request(
432
+ :request=>req
433
+ ).should == 'oob'
434
+ end
435
+ end
436
+
437
+ end
438
+
439
+
440
+ describe 'expecting a request for a token credential' do
441
+ before do
442
+ @client = Signet::OAuth1::Client.new(
443
+ :client_credential_key=>@client_credential_key,
444
+ :client_credential_secret=>@client_credential_secret,
445
+ :temporary_credential_key=>@temporary_credential_key,
446
+ :temporary_credential_secret=>@temporary_credential_secret,
447
+ :token_credential_uri=>'http://photos.example.net/token'
448
+ )
449
+ @return_hash = {:client_credential=>Signet::OAuth1::Credential.new(@client_credential_key, @client_credential_secret),
450
+ :temporary_credential=>Signet::OAuth1::Credential.new(@temporary_credential_key, @temporary_credential_secret),
451
+ :realm=>nil
452
+ }
453
+ end
454
+
455
+ it 'should reject an malformed request' do
456
+ bad_request = make_token_credential_request(@client)
457
+ bad_request.headers["Authorization"].gsub!(/(OAuth)(.+)/, "#{$1}")
458
+
459
+ (lambda do
460
+ @server.authenticate_token_credential_request(
461
+ :request=>bad_request
462
+ )
463
+ end).should raise_error(Signet::MalformedAuthorizationError)
464
+ end
465
+ it 'should call a user-supplied Proc to validate a nonce/timestamp pair' do
466
+ nonce_callback = mock('nonce')
467
+ nonce_callback.should_receive(:call).once.with(
468
+ an_instance_of(String), an_instance_of(String)
469
+ ).and_return(true)
470
+ @server.nonce_timestamp = nonce_callback
471
+ @server.authenticate_token_credential_request(
472
+ :request=>make_token_credential_request(@client)
473
+ )
474
+ end
475
+ it 'should return an informational hash for a valid request' do
476
+ @server.authenticate_token_credential_request(
477
+ :request=>make_token_credential_request(@client)
478
+ ).should == @return_hash
479
+ end
480
+ it 'should return nil for an unauthenticated request' do
481
+ bad_request = make_token_credential_request(@client)
482
+ bad_request.headers["Authorization"].gsub!(/oauth_signature=\".+\"/,
483
+ "oauth_signature=\"foobar\"")
484
+ @server.authenticate_token_credential_request(
485
+ :request=>bad_request
486
+ ).should == nil
487
+ end
488
+ it 'should call a user-supplied Proc to fetch the client credential' do
489
+ client_cred = Signet::OAuth1::Credential.new(@client_credential_key,
490
+ @client_credential_secret )
491
+ key_callback = mock('client_cred')
492
+ key_callback.should_receive(:call).at_least(:once).with(
493
+ @client_credential_key
494
+ ).and_return(client_cred)
495
+
496
+ @server.client_credential = key_callback
497
+ @server.authenticate_token_credential_request(
498
+ :request=>make_token_credential_request(@client)
499
+ )
500
+ end
501
+
502
+ it 'should call a user-supplied Proc to fetch the temporary token credential' do
503
+ temp_cred = Signet::OAuth1::Credential.new(@temporary_credential_key,
504
+ @temporary_credential_secret)
505
+ temp_callback = mock('temp_cred')
506
+ temp_callback.should_receive(:call).at_least(:once).with(
507
+ @temporary_credential_key
508
+ ).and_return(temp_cred)
509
+
510
+ @server.temporary_credential = temp_callback
511
+ @server.authenticate_token_credential_request(
512
+ :request=>make_token_credential_request(@client)
513
+ )
514
+ end
515
+ it 'should return nil from #request_realm if no realm is provided' do
516
+ req = make_token_credential_request(@client)
517
+ @server.request_realm(
518
+ :request=>req
519
+ ).should == nil
520
+ end
521
+
522
+ describe 'with a Realm provided' do
523
+ before do
524
+ @realm = 'Photos'
525
+ @return_hash[:realm] = @realm
526
+ end
527
+ it 'should return the realm from #request_realm' do
528
+ req = make_token_credential_request(@client, nil, @realm)
529
+ @server.request_realm(
530
+ :request=>req
531
+ ).should == @realm
532
+ end
533
+ it 'should an informational hash with a valid request' do
534
+ req = make_token_credential_request(@client, nil, @realm)
535
+ @server.authenticate_token_credential_request(
536
+ :request=>req
537
+ ).should == @return_hash
538
+ end
539
+ end
540
+
541
+ end
542
+
543
+
544
+ describe 'expecting a request for a protected resource' do
545
+ before(:each) do
546
+ @client = Signet::OAuth1::Client.new(
547
+ :client_credential_key=>@client_credential_key,
548
+ :client_credential_secret=>@client_credential_secret,
549
+ :token_credential_key=>@token_credential_key,
550
+ :token_credential_secret=>@token_credential_secret
551
+ )
552
+ @return_hash = {:client_credential=>Signet::OAuth1::Credential.new(@client_credential_key, @client_credential_secret),
553
+ :token_credential=>Signet::OAuth1::Credential.new(@token_credential_key, @token_credential_secret),
554
+ :realm=>nil
555
+ }
556
+ end
557
+
558
+ it 'should not raise an error if a request body is chunked(as Array)' do
559
+ approved = @server.authenticate_resource_request(
560
+ :method => 'POST',
561
+ :uri => 'https://photos.example.net/photos',
562
+ :body => ['A chunked body.'],
563
+ :headers => make_oauth_signature_header
564
+ )
565
+ approved.should == nil
566
+ end
567
+
568
+ it 'should not raise an error if a request body is chunked(as StringIO)' do
569
+ chunked_body = StringIO.new
570
+ chunked_body.write('A chunked body.')
571
+ chunked_body.rewind
572
+ approved = @server.authenticate_resource_request(
573
+ :method => 'POST',
574
+ :uri => 'https://photos.example.net/photos',
575
+ :body => chunked_body,
576
+ :headers => make_oauth_signature_header
577
+ )
578
+ approved.should == nil
579
+ end
580
+
581
+ it 'should raise an error if a request body is of a bogus type' do
582
+ (lambda do
583
+ @server.authenticate_resource_request(
584
+ :method => 'POST',
585
+ :uri => 'https://photos.example.net/photos',
586
+ :body => 42,
587
+ :headers => make_oauth_signature_header
588
+ )
589
+ end).should raise_error(TypeError)
590
+ end
591
+ it 'should use form parameters in signature if request is a POSTed form' do
592
+ req = make_resource_request(
593
+ @client,
594
+ {:method=>'POST',
595
+ :headers=>{'Content-Type'=>'application/x-www-form-urlencoded'},
596
+ :body=>'c2&a3=2+q'})
597
+ @server.authenticate_resource_request(:request=>req).should == @return_hash
598
+ end
599
+ it 'should raise an error if signature is x-www-form-encoded ' +
600
+ 'but does not send form parameters in header' do
601
+
602
+ # Make a full request so that we can sign against the form parameters
603
+ # that will be removed.
604
+ req = make_resource_request(
605
+ @client,
606
+ {:method=>'POST',
607
+ :headers=>{'Content-Type'=>'application/x-www-form-urlencoded'},
608
+ :body=>'c2&a3=2+q'})
609
+
610
+ req.headers["Authorization"].gsub!(/c2=\"\", a3=\"2%20q\", /, '')
611
+
612
+ (lambda do
613
+ @server.authenticate_resource_request(:request=>req)
614
+ end).should raise_error(Signet::MalformedAuthorizationError,
615
+ 'Request is of type application/x-www-form-urlencoded but ' +
616
+ 'Authentication header did not include form values'
617
+ )
618
+ end
619
+
620
+ it 'should call a user-supplied Proc to validate a nonce/timestamp pair' do
621
+ nonce_callback = mock('nonce')
622
+ nonce_callback.should_receive(:call).once.with(
623
+ an_instance_of(String), an_instance_of(String)
624
+ ).and_return(true)
625
+
626
+ @server.nonce_timestamp = nonce_callback
627
+ @server.authenticate_resource_request(
628
+ :request=>make_resource_request(@client)
629
+ )
630
+ end
631
+
632
+ it 'should call a user-supplied Proc to fetch the client credential' do
633
+ client_cred = Signet::OAuth1::Credential.new(@client_credential_key,
634
+ @client_credential_secret )
635
+ key_callback = mock('client_cred' )
636
+ key_callback.should_receive(:call).at_least(:once).with(
637
+ @client_credential_key
638
+ ).and_return(client_cred)
639
+
640
+ @server.client_credential = key_callback
641
+ @server.authenticate_resource_request(
642
+ :request=>make_resource_request(@client)
643
+ )
644
+ end
645
+
646
+ it 'should call a user-supplied Proc to fetch the token credential' do
647
+ token_cred = Signet::OAuth1::Credential.new(@token_credential_key,
648
+ @token_credential_secret)
649
+ key_callback = mock('token_cred' )
650
+ key_callback.should_receive(:call).at_least(:once).with(
651
+ @token_credential_key
652
+ ).and_return(token_cred)
653
+
654
+ @server.token_credential = key_callback
655
+ @server.authenticate_resource_request(
656
+ :request=>make_resource_request(@client)
657
+ )
658
+ end
659
+
660
+ it 'should return a Hash for a valid request' do
661
+ @server.authenticate_resource_request(
662
+ :request=>make_resource_request(@client)
663
+ ).should == @return_hash
664
+ end
665
+ it 'should return nil for a unauthenticated request' do
666
+ bad_request = make_resource_request(@client)
667
+ bad_request.headers["Authorization"].gsub!(/oauth_signature=\".+\"/,
668
+ "oauth_signature=\"foobar\"")
669
+ @server.authenticate_resource_request(:request=>bad_request).should == nil
670
+ end
671
+ it 'should return nil from #request_realm if no realm is provided' do
672
+ req = make_resource_request(@client)
673
+ @server.request_realm(
674
+ :request=>req
675
+ ).should == nil
676
+ end
677
+
678
+ describe 'with a Realm provided' do
679
+ before do
680
+ @realm = 'Photos'
681
+ @return_hash[:realm] = @realm
682
+ end
683
+ it 'should return the realm from #request_realm' do
684
+ req = make_resource_request(@client, {}, @realm)
685
+ @server.request_realm(
686
+ :request=>req
687
+ ).should == @realm
688
+ end
689
+ it 'should return a hash containing the realm with a valid request' do
690
+ req = make_resource_request(@client, {}, @realm)
691
+ @server.authenticate_resource_request(
692
+ :request=>req
693
+ ).should == @return_hash
694
+ end
695
+ end
696
+
697
+ end
698
+
699
+
700
+ describe "expecting a two-legged request for a protected resource" do
701
+ before do
702
+ @client = Signet::OAuth1::Client.new(
703
+ :client_credential_key=>@client_credential_key,
704
+ :client_credential_secret=>@client_credential_secret,
705
+ :two_legged=>true)
706
+
707
+ @return_hash = {:client_credential=>Signet::OAuth1::Credential.new(@client_credential_key, @client_credential_secret),
708
+ :token_credential=>nil,
709
+ :realm=>nil
710
+ }
711
+ end
712
+ it 'should not raise an error if a request body is chunked(as Array)' do
713
+ approved = @server.authenticate_resource_request(
714
+ :method => 'POST',
715
+ :uri => 'https://photos.example.net/photos',
716
+ :body => ['A chunked body.'],
717
+ :headers => make_oauth_signature_header,
718
+ :two_legged=>true
719
+ )
720
+ approved.should == nil
721
+ end
722
+
723
+ it 'should not raise an error if a request body is chunked(as StringIO)' do
724
+ chunked_body = StringIO.new
725
+ chunked_body.write('A chunked body.')
726
+ chunked_body.rewind
727
+ approved = @server.authenticate_resource_request(
728
+ :method => 'POST',
729
+ :uri => 'https://photos.example.net/photos',
730
+ :body => chunked_body,
731
+ :headers => make_oauth_signature_header,
732
+ :two_legged=>true
733
+ )
734
+ approved.should == nil
735
+ end
736
+
737
+ it 'should raise an error if a request body is of a bogus type' do
738
+ (lambda do
739
+ @server.authenticate_resource_request(
740
+ :method => 'POST',
741
+ :uri => 'https://photos.example.net/photos',
742
+ :body => 42,
743
+ :headers => make_oauth_signature_header,
744
+ :two_legged=>true
745
+ )
746
+ end).should raise_error(TypeError)
747
+ end
748
+ it 'should use form parameters in signature if request is a POSTed form' do
749
+ req = make_resource_request(
750
+ @client,
751
+ {:method=>'POST',
752
+ :headers=>{'Content-Type'=>'application/x-www-form-urlencoded'},
753
+ :body=>'c2&a3=2+q'}
754
+ )
755
+ @server.authenticate_resource_request(
756
+ :request=>req, :two_legged=>true
757
+ ).should == @return_hash
758
+ end
759
+ it 'should raise an error if signature is x-www-form-encoded '+
760
+ 'but does not send form parameters in header' do
761
+
762
+ # Make a full request so that we can sign against the form parameters
763
+ # that will be removed.
764
+ req = make_resource_request(
765
+ @client,
766
+ {:method=>'POST',
767
+ :headers=>{'Content-Type'=>'application/x-www-form-urlencoded'},
768
+ :body=>'c2&a3=2+q'}
769
+ )
770
+
771
+ req.headers["Authorization"].gsub!(/c2=\"\", a3=\"2%20q\", /, '')
772
+
773
+ (lambda do
774
+ @server.authenticate_resource_request(:request=>req, :two_legged=>true)
775
+ end).should raise_error(Signet::MalformedAuthorizationError,
776
+ 'Request is of type application/x-www-form-urlencoded but '+
777
+ 'Authentication header did not include form values'
778
+ )
779
+ end
780
+
781
+ it 'should call a user-supplied Proc to validate a nonce/timestamp pair' do
782
+ nonce_callback = mock('nonce')
783
+ nonce_callback.should_receive(:call).once.with(
784
+ an_instance_of(String), an_instance_of(String)
785
+ ).and_return(true)
786
+
787
+ @server.nonce_timestamp = nonce_callback
788
+ @server.authenticate_resource_request(
789
+ :request=>make_resource_request(@client), :two_legged=>true
790
+ )
791
+ end
792
+
793
+ it 'should call a user-supplied Proc to fetch the client credential' do
794
+ client_cred = Signet::OAuth1::Credential.new(@client_credential_key,
795
+ @client_credential_secret )
796
+ key_callback = mock('client_cred')
797
+ key_callback.should_receive(:call).at_least(:once).with(
798
+ @client_credential_key
799
+ ).and_return(client_cred)
800
+
801
+ @server.client_credential = key_callback
802
+ @server.authenticate_resource_request(
803
+ :request=>make_resource_request(@client), :two_legged=>true
804
+ )
805
+ end
806
+
807
+ it 'should return a informational hash for a valid request' do
808
+ @server.authenticate_resource_request(
809
+ :request=>make_resource_request(@client), :two_legged=>true
810
+ ).should == @return_hash
811
+ end
812
+ it 'should return false for a unauthenticated request' do
813
+ bad_request = make_resource_request(@client)
814
+ bad_request.headers["Authorization"].gsub!(/oauth_signature=\".+\"/,
815
+ "oauth_signature=\"foobar\"")
816
+ @server.authenticate_resource_request(:request=>bad_request).should == nil
817
+ end
818
+ it 'should return nil from #request_realm if no realm is provided' do
819
+ req = make_resource_request(@client)
820
+ @server.request_realm(
821
+ :request=>req
822
+ ).should == nil
823
+ end
824
+ describe 'with a Realm provided' do
825
+ before do
826
+ @realm = 'Photos'
827
+ @return_hash[:realm] = @realm
828
+ end
829
+ it 'should return the realm from #request_realm' do
830
+ req = make_resource_request(@client, {}, @realm)
831
+ @server.request_realm(
832
+ :request=>req, :two_legged=>true
833
+ ).should == @realm
834
+ end
835
+
836
+ it 'should return a hash containing the realm with a valid request' do
837
+ req = make_resource_request(@client, {}, @realm)
838
+ @server.authenticate_resource_request(
839
+ :request=>req, :two_legged=>true
840
+ ).should == @return_hash
841
+ end
842
+ end
843
+
844
+ end
845
+
846
+ end