oauth_weshays 0.4.8.pre

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 (89) hide show
  1. checksums.yaml +15 -0
  2. data/.gemtest +0 -0
  3. data/Gemfile +16 -0
  4. data/Gemfile.lock +47 -0
  5. data/HISTORY +173 -0
  6. data/LICENSE +20 -0
  7. data/README.rdoc +75 -0
  8. data/Rakefile +37 -0
  9. data/TODO +32 -0
  10. data/bin/oauth +5 -0
  11. data/examples/yql.rb +44 -0
  12. data/lib/digest/hmac.rb +104 -0
  13. data/lib/oauth/cli.rb +378 -0
  14. data/lib/oauth/client/action_controller_request.rb +65 -0
  15. data/lib/oauth/client/em_http.rb +120 -0
  16. data/lib/oauth/client/helper.rb +91 -0
  17. data/lib/oauth/client/net_http.rb +120 -0
  18. data/lib/oauth/client.rb +4 -0
  19. data/lib/oauth/consumer.rb +389 -0
  20. data/lib/oauth/core_ext.rb +31 -0
  21. data/lib/oauth/errors/error.rb +4 -0
  22. data/lib/oauth/errors/problem.rb +14 -0
  23. data/lib/oauth/errors/unauthorized.rb +12 -0
  24. data/lib/oauth/errors.rb +3 -0
  25. data/lib/oauth/helper.rb +109 -0
  26. data/lib/oauth/oauth.rb +13 -0
  27. data/lib/oauth/oauth_test_helper.rb +25 -0
  28. data/lib/oauth/request_proxy/action_controller_request.rb +62 -0
  29. data/lib/oauth/request_proxy/base.rb +174 -0
  30. data/lib/oauth/request_proxy/curb_request.rb +55 -0
  31. data/lib/oauth/request_proxy/em_http_request.rb +66 -0
  32. data/lib/oauth/request_proxy/jabber_request.rb +41 -0
  33. data/lib/oauth/request_proxy/mock_request.rb +44 -0
  34. data/lib/oauth/request_proxy/net_http.rb +73 -0
  35. data/lib/oauth/request_proxy/rack_request.rb +44 -0
  36. data/lib/oauth/request_proxy/typhoeus_request.rb +53 -0
  37. data/lib/oauth/request_proxy.rb +24 -0
  38. data/lib/oauth/server.rb +66 -0
  39. data/lib/oauth/signature/base.rb +110 -0
  40. data/lib/oauth/signature/hmac/base.rb +15 -0
  41. data/lib/oauth/signature/hmac/md5.rb +8 -0
  42. data/lib/oauth/signature/hmac/rmd160.rb +8 -0
  43. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  44. data/lib/oauth/signature/hmac/sha2.rb +8 -0
  45. data/lib/oauth/signature/md5.rb +13 -0
  46. data/lib/oauth/signature/plaintext.rb +23 -0
  47. data/lib/oauth/signature/rsa/sha1.rb +46 -0
  48. data/lib/oauth/signature/sha1.rb +13 -0
  49. data/lib/oauth/signature.rb +45 -0
  50. data/lib/oauth/token.rb +7 -0
  51. data/lib/oauth/tokens/access_token.rb +71 -0
  52. data/lib/oauth/tokens/consumer_token.rb +33 -0
  53. data/lib/oauth/tokens/request_token.rb +32 -0
  54. data/lib/oauth/tokens/server_token.rb +9 -0
  55. data/lib/oauth/tokens/token.rb +17 -0
  56. data/lib/oauth.rb +13 -0
  57. data/oauth.gemspec +148 -0
  58. data/tasks/deployment.rake +34 -0
  59. data/tasks/environment.rake +7 -0
  60. data/tasks/website.rake +17 -0
  61. data/test/cases/oauth_case.rb +19 -0
  62. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  63. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  64. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  65. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  66. data/test/integration/consumer_test.rb +307 -0
  67. data/test/keys/rsa.cert +11 -0
  68. data/test/keys/rsa.pem +16 -0
  69. data/test/test_access_token.rb +26 -0
  70. data/test/test_action_controller_request_proxy.rb +133 -0
  71. data/test/test_consumer.rb +220 -0
  72. data/test/test_curb_request_proxy.rb +77 -0
  73. data/test/test_em_http_client.rb +80 -0
  74. data/test/test_em_http_request_proxy.rb +115 -0
  75. data/test/test_helper.rb +28 -0
  76. data/test/test_hmac_sha1.rb +20 -0
  77. data/test/test_net_http_client.rb +292 -0
  78. data/test/test_net_http_request_proxy.rb +72 -0
  79. data/test/test_oauth_helper.rb +94 -0
  80. data/test/test_rack_request_proxy.rb +40 -0
  81. data/test/test_request_token.rb +51 -0
  82. data/test/test_rsa_sha1.rb +59 -0
  83. data/test/test_server.rb +40 -0
  84. data/test/test_signature.rb +22 -0
  85. data/test/test_signature_base.rb +32 -0
  86. data/test/test_signature_plain_text.rb +31 -0
  87. data/test/test_token.rb +14 -0
  88. data/test/test_typhoeus_request_proxy.rb +80 -0
  89. metadata +252 -0
data/lib/oauth/cli.rb ADDED
@@ -0,0 +1,378 @@
1
+ require 'optparse'
2
+ require 'oauth'
3
+
4
+ module OAuth
5
+ class CLI
6
+ SUPPORTED_COMMANDS = {
7
+ "authorize" => "Obtain an access token and secret for a user",
8
+ "debug" => "Verbosely generate an OAuth signature",
9
+ "query" => "Query a protected resource",
10
+ "sign" => "Generate an OAuth signature",
11
+ "version" => "Display the current version of the library"
12
+ }
13
+
14
+ attr_reader :command
15
+ attr_reader :options
16
+ attr_reader :stdout, :stdin
17
+
18
+ def self.execute(stdout, stdin, stderr, arguments = [])
19
+ self.new.execute(stdout, stdin, stderr, arguments)
20
+ end
21
+
22
+ def initialize
23
+ @options = {}
24
+
25
+ # don't dump a backtrace on a ^C
26
+ trap(:INT) {
27
+ exit
28
+ }
29
+ end
30
+
31
+ def execute(stdout, stdin, stderr, arguments = [])
32
+ @stdout = stdout
33
+ @stdin = stdin
34
+ @stderr = stderr
35
+ extract_command_and_parse_options(arguments)
36
+
37
+ if sufficient_options? && valid_command?
38
+ if command == "debug"
39
+ @command = "sign"
40
+ @options[:verbose] = true
41
+ end
42
+
43
+ case command
44
+ # TODO move command logic elsewhere
45
+ when "authorize"
46
+ begin
47
+ consumer = OAuth::Consumer.new \
48
+ options[:oauth_consumer_key],
49
+ options[:oauth_consumer_secret],
50
+ :access_token_url => options[:access_token_url],
51
+ :authorize_url => options[:authorize_url],
52
+ :request_token_url => options[:request_token_url],
53
+ :scheme => options[:scheme],
54
+ :http_method => options[:method].to_s.downcase.to_sym
55
+
56
+ # parameters for OAuth 1.0a
57
+ oauth_verifier = nil
58
+
59
+ # get a request token
60
+ request_token = consumer.get_request_token({ :oauth_callback => options[:oauth_callback] }, { "scope" => options[:scope] })
61
+
62
+ if request_token.callback_confirmed?
63
+ stdout.puts "Server appears to support OAuth 1.0a; enabling support."
64
+ options[:version] = "1.0a"
65
+ end
66
+
67
+ stdout.puts "Please visit this url to authorize:"
68
+ stdout.puts request_token.authorize_url
69
+
70
+ if options[:version] == "1.0a"
71
+ stdout.puts "Please enter the verification code provided by the SP (oauth_verifier):"
72
+ oauth_verifier = stdin.gets.chomp
73
+ else
74
+ stdout.puts "Press return to continue..."
75
+ stdin.gets
76
+ end
77
+
78
+ begin
79
+ # get an access token
80
+ access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
81
+
82
+ stdout.puts "Response:"
83
+ access_token.params.each do |k,v|
84
+ stdout.puts " #{k}: #{v}" unless k.is_a?(Symbol)
85
+ end
86
+ rescue OAuth::Unauthorized => e
87
+ stderr.puts "A problem occurred while attempting to obtain an access token:"
88
+ stderr.puts e
89
+ stderr.puts e.request.body
90
+ end
91
+ rescue OAuth::Unauthorized => e
92
+ stderr.puts "A problem occurred while attempting to authorize:"
93
+ stderr.puts e
94
+ stderr.puts e.request.body
95
+ end
96
+ when "query"
97
+ consumer = OAuth::Consumer.new \
98
+ options[:oauth_consumer_key],
99
+ options[:oauth_consumer_secret],
100
+ :scheme => options[:scheme]
101
+
102
+ access_token = OAuth::AccessToken.new(consumer, options[:oauth_token], options[:oauth_token_secret])
103
+
104
+ # append params to the URL
105
+ uri = URI.parse(options[:uri])
106
+ params = prepare_parameters.map { |k,v| v.map { |v2| "#{URI.encode(k)}=#{URI.encode(v2)}" } * "&" }
107
+ uri.query = [uri.query, *params].reject { |x| x.nil? } * "&"
108
+ p uri.to_s
109
+
110
+ response = access_token.request(options[:method].downcase.to_sym, uri.to_s)
111
+ puts "#{response.code} #{response.message}"
112
+ puts response.body
113
+ when "sign"
114
+ parameters = prepare_parameters
115
+
116
+ request = OAuth::RequestProxy.proxy \
117
+ "method" => options[:method],
118
+ "uri" => options[:uri],
119
+ "parameters" => parameters
120
+
121
+ if verbose?
122
+ stdout.puts "OAuth parameters:"
123
+ request.oauth_parameters.each do |k,v|
124
+ stdout.puts " " + [k, v] * ": "
125
+ end
126
+ stdout.puts
127
+
128
+ if request.non_oauth_parameters.any?
129
+ stdout.puts "Parameters:"
130
+ request.non_oauth_parameters.each do |k,v|
131
+ stdout.puts " " + [k, v] * ": "
132
+ end
133
+ stdout.puts
134
+ end
135
+ end
136
+
137
+ request.sign! \
138
+ :consumer_secret => options[:oauth_consumer_secret],
139
+ :token_secret => options[:oauth_token_secret]
140
+
141
+ if verbose?
142
+ stdout.puts "Method: #{request.method}"
143
+ stdout.puts "URI: #{request.uri}"
144
+ stdout.puts "Normalized params: #{request.normalized_parameters}" unless options[:xmpp]
145
+ stdout.puts "Signature base string: #{request.signature_base_string}"
146
+
147
+ if options[:xmpp]
148
+ stdout.puts
149
+ stdout.puts "XMPP Stanza:"
150
+ stdout.puts <<-EOS
151
+ <oauth xmlns='urn:xmpp:oauth:0'>
152
+ <oauth_consumer_key>#{request.oauth_consumer_key}</oauth_consumer_key>
153
+ <oauth_token>#{request.oauth_token}</oauth_token>
154
+ <oauth_signature_method>#{request.oauth_signature_method}</oauth_signature_method>
155
+ <oauth_signature>#{request.oauth_signature}</oauth_signature>
156
+ <oauth_timestamp>#{request.oauth_timestamp}</oauth_timestamp>
157
+ <oauth_nonce>#{request.oauth_nonce}</oauth_nonce>
158
+ <oauth_version>#{request.oauth_version}</oauth_version>
159
+ </oauth>
160
+ EOS
161
+ stdout.puts
162
+ stdout.puts "Note: You may want to use bare JIDs in your URI."
163
+ stdout.puts
164
+ else
165
+ stdout.puts "OAuth Request URI: #{request.signed_uri}"
166
+ stdout.puts "Request URI: #{request.signed_uri(false)}"
167
+ stdout.puts "Authorization header: #{request.oauth_header(:realm => options[:realm])}"
168
+ end
169
+ stdout.puts "Signature: #{request.oauth_signature}"
170
+ stdout.puts "Escaped signature: #{OAuth::Helper.escape(request.oauth_signature)}"
171
+ else
172
+ stdout.puts request.oauth_signature
173
+ end
174
+ when "version"
175
+ puts "OAuth for Ruby #{OAuth::VERSION}"
176
+ end
177
+ else
178
+ usage
179
+ end
180
+ end
181
+
182
+ protected
183
+
184
+ def extract_command_and_parse_options(arguments)
185
+ @command = arguments[-1]
186
+ parse_options(arguments[0..-1])
187
+ end
188
+
189
+ def option_parser(arguments = "")
190
+ # TODO add realm parameter
191
+ # TODO add user-agent parameter
192
+ option_parser = OptionParser.new do |opts|
193
+ opts.banner = "Usage: #{$0} [options] <command>"
194
+
195
+ # defaults
196
+ options[:oauth_nonce] = OAuth::Helper.generate_key
197
+ options[:oauth_signature_method] = "HMAC-SHA1"
198
+ options[:oauth_timestamp] = OAuth::Helper.generate_timestamp
199
+ options[:oauth_version] = "1.0"
200
+ options[:method] = :post
201
+ options[:params] = []
202
+ options[:scheme] = :header
203
+ options[:version] = "1.0"
204
+
205
+ ## Common Options
206
+
207
+ opts.on("-B", "--body", "Use the request body for OAuth parameters.") do
208
+ options[:scheme] = :body
209
+ end
210
+
211
+ opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
212
+ options[:oauth_consumer_key] = v
213
+ end
214
+
215
+ opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
216
+ options[:oauth_consumer_secret] = v
217
+ end
218
+
219
+ opts.on("-H", "--header", "Use the 'Authorization' header for OAuth parameters (default).") do
220
+ options[:scheme] = :header
221
+ end
222
+
223
+ opts.on("-Q", "--query-string", "Use the query string for OAuth parameters.") do
224
+ options[:scheme] = :query_string
225
+ end
226
+
227
+ opts.on("-O", "--options FILE", "Read options from a file") do |v|
228
+ arguments.unshift(*open(v).readlines.map { |l| l.chomp.split(" ") }.flatten)
229
+ end
230
+
231
+ ## Options for signing and making requests
232
+
233
+ opts.separator("\n options for signing and querying")
234
+
235
+ opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
236
+ options[:method] = v
237
+ end
238
+
239
+ opts.on("--nonce NONCE", "Specifies the none to use.") do |v|
240
+ options[:oauth_nonce] = v
241
+ end
242
+
243
+ opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
244
+ options[:params] << v
245
+ end
246
+
247
+ opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
248
+ options[:oauth_signature_method] = v
249
+ end
250
+
251
+ opts.on("--secret SECRET", "Specifies the token secret to use.") do |v|
252
+ options[:oauth_token_secret] = v
253
+ end
254
+
255
+ opts.on("--timestamp TIMESTAMP", "Specifies the timestamp to use.") do |v|
256
+ options[:oauth_timestamp] = v
257
+ end
258
+
259
+ opts.on("--token TOKEN", "Specifies the token to use.") do |v|
260
+ options[:oauth_token] = v
261
+ end
262
+
263
+ opts.on("--realm REALM", "Specifies the realm to use.") do |v|
264
+ options[:realm] = v
265
+ end
266
+
267
+ opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
268
+ options[:uri] = v
269
+ end
270
+
271
+ opts.on(:OPTIONAL, "--version VERSION", "Specifies the OAuth version to use.") do |v|
272
+ if v
273
+ options[:oauth_version] = v
274
+ else
275
+ @command = "version"
276
+ end
277
+ end
278
+
279
+ opts.on("--no-version", "Omit oauth_version.") do
280
+ options[:oauth_version] = nil
281
+ end
282
+
283
+ opts.on("--xmpp", "Generate XMPP stanzas.") do
284
+ options[:xmpp] = true
285
+ options[:method] ||= "iq"
286
+ end
287
+
288
+ opts.on("-v", "--verbose", "Be verbose.") do
289
+ options[:verbose] = true
290
+ end
291
+
292
+ ## Options for authorization
293
+
294
+ opts.separator("\n options for authorization")
295
+
296
+ opts.on("--access-token-url URL", "Specifies the access token URL.") do |v|
297
+ options[:access_token_url] = v
298
+ end
299
+
300
+ opts.on("--authorize-url URL", "Specifies the authorization URL.") do |v|
301
+ options[:authorize_url] = v
302
+ end
303
+
304
+ opts.on("--callback-url URL", "Specifies a callback URL.") do |v|
305
+ options[:oauth_callback] = v
306
+ end
307
+
308
+ opts.on("--request-token-url URL", "Specifies the request token URL.") do |v|
309
+ options[:request_token_url] = v
310
+ end
311
+
312
+ opts.on("--scope SCOPE", "Specifies the scope (Google-specific).") do |v|
313
+ options[:scope] = v
314
+ end
315
+ end
316
+ end
317
+
318
+ def parse_options(arguments)
319
+ option_parser(arguments).parse!(arguments)
320
+ end
321
+
322
+ def prepare_parameters
323
+ escaped_pairs = options[:params].collect do |pair|
324
+ if pair =~ /:/
325
+ Hash[*pair.split(":", 2)].collect do |k,v|
326
+ [CGI.escape(k.strip), CGI.escape(v.strip)] * "="
327
+ end
328
+ else
329
+ pair
330
+ end
331
+ end
332
+
333
+ querystring = escaped_pairs * "&"
334
+ cli_params = CGI.parse(querystring)
335
+
336
+ {
337
+ "oauth_consumer_key" => options[:oauth_consumer_key],
338
+ "oauth_nonce" => options[:oauth_nonce],
339
+ "oauth_timestamp" => options[:oauth_timestamp],
340
+ "oauth_token" => options[:oauth_token],
341
+ "oauth_signature_method" => options[:oauth_signature_method],
342
+ "oauth_version" => options[:oauth_version]
343
+ }.reject { |k,v| v.nil? || v == "" }.merge(cli_params)
344
+ end
345
+
346
+ def sufficient_options?
347
+ case command
348
+ # TODO move command logic elsewhere
349
+ when "authorize"
350
+ options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
351
+ options[:access_token_url] && options[:authorize_url] &&
352
+ options[:request_token_url]
353
+ when "version"
354
+ true
355
+ else
356
+ options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
357
+ options[:method] && options[:uri]
358
+ end
359
+ end
360
+
361
+ def usage
362
+ stdout.puts option_parser.help
363
+ stdout.puts
364
+ stdout.puts "Available commands:"
365
+ SUPPORTED_COMMANDS.each do |command, desc|
366
+ puts " #{command.ljust(15)}#{desc}"
367
+ end
368
+ end
369
+
370
+ def valid_command?
371
+ SUPPORTED_COMMANDS.keys.include?(command)
372
+ end
373
+
374
+ def verbose?
375
+ options[:verbose]
376
+ end
377
+ end
378
+ end
@@ -0,0 +1,65 @@
1
+ require 'oauth/client/helper'
2
+ if defined? ActionDispatch
3
+ require 'oauth/request_proxy/rack_request'
4
+ require 'action_dispatch/testing/test_process'
5
+ else
6
+ require 'oauth/request_proxy/action_controller_request'
7
+ require 'action_controller/test_process'
8
+ end
9
+
10
+ module ActionController
11
+ class Base
12
+ if defined? ActionDispatch
13
+ def process_with_new_base_test(request, response=nil)
14
+ request.apply_oauth! if request.respond_to?(:apply_oauth!)
15
+ super(request, response)
16
+ end
17
+ else
18
+ def process_with_oauth(request, response=nil)
19
+ request.apply_oauth! if request.respond_to?(:apply_oauth!)
20
+ process_without_oauth(request, response)
21
+ end
22
+ alias_method_chain :process, :oauth
23
+ end
24
+ end
25
+
26
+ class TestRequest
27
+ def self.use_oauth=(bool)
28
+ @use_oauth = bool
29
+ end
30
+
31
+ def self.use_oauth?
32
+ @use_oauth
33
+ end
34
+
35
+ def configure_oauth(consumer = nil, token = nil, options = {})
36
+ @oauth_options = { :consumer => consumer,
37
+ :token => token,
38
+ :scheme => 'header',
39
+ :signature_method => nil,
40
+ :nonce => nil,
41
+ :timestamp => nil }.merge(options)
42
+ end
43
+
44
+ def apply_oauth!
45
+ return unless ActionController::TestRequest.use_oauth? && @oauth_options
46
+
47
+ @oauth_helper = OAuth::Client::Helper.new(self, @oauth_options.merge(:request_uri => (respond_to?(:fullpath) ? fullpath : request_uri)))
48
+ @oauth_helper.amend_user_agent_header(env)
49
+
50
+ self.send("set_oauth_#{@oauth_options[:scheme]}")
51
+ end
52
+
53
+ def set_oauth_header
54
+ env['Authorization'] = @oauth_helper.header
55
+ end
56
+
57
+ def set_oauth_parameters
58
+ @query_parameters = @oauth_helper.parameters_with_oauth
59
+ @query_parameters.merge!(:oauth_signature => @oauth_helper.signature)
60
+ end
61
+
62
+ def set_oauth_query_string
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,120 @@
1
+ require 'em-http'
2
+ require 'oauth/helper'
3
+ require 'oauth/client/helper'
4
+ require 'oauth/request_proxy/em_http_request'
5
+
6
+ # Extensions for em-http so that we can use consumer.sign! with an EventMachine::HttpClient
7
+ # instance. This is purely syntactic sugar.
8
+ class EventMachine::HttpClient
9
+
10
+ attr_reader :oauth_helper
11
+
12
+ # Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> setting
13
+ # this may add a header, additional query string parameters, or additional POST body parameters.
14
+ # The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
15
+ # header.
16
+ #
17
+ # * http - Configured Net::HTTP instance, ignored in this scenario except for getting host.
18
+ # * consumer - OAuth::Consumer instance
19
+ # * token - OAuth::Token instance
20
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
21
+ # +signature_method+, +nonce+, +timestamp+)
22
+ #
23
+ # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
24
+ #
25
+ # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1]
26
+ def oauth!(http, consumer = nil, token = nil, options = {})
27
+ options = { :request_uri => normalized_oauth_uri(http),
28
+ :consumer => consumer,
29
+ :token => token,
30
+ :scheme => 'header',
31
+ :signature_method => nil,
32
+ :nonce => nil,
33
+ :timestamp => nil }.merge(options)
34
+
35
+ @oauth_helper = OAuth::Client::Helper.new(self, options)
36
+ self.__send__(:"set_oauth_#{options[:scheme]}")
37
+ end
38
+
39
+ # Create a string suitable for signing for an HTTP request. This process involves parameter
40
+ # normalization as specified in the OAuth specification. The exact normalization also depends
41
+ # on the <tt>options[:scheme]</tt> being used so this must match what will be used for the request
42
+ # itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
43
+ # header.
44
+ #
45
+ # * http - Configured Net::HTTP instance
46
+ # * consumer - OAuth::Consumer instance
47
+ # * token - OAuth::Token instance
48
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
49
+ # +signature_method+, +nonce+, +timestamp+)
50
+ #
51
+ # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
52
+ def signature_base_string(http, consumer = nil, token = nil, options = {})
53
+ options = { :request_uri => normalized_oauth_uri(http),
54
+ :consumer => consumer,
55
+ :token => token,
56
+ :scheme => 'header',
57
+ :signature_method => nil,
58
+ :nonce => nil,
59
+ :timestamp => nil }.merge(options)
60
+
61
+ OAuth::Client::Helper.new(self, options).signature_base_string
62
+ end
63
+
64
+ # This code was lifted from the em-http-request because it was removed from
65
+ # the gem June 19, 2010
66
+ # see: http://github.com/igrigorik/em-http-request/commit/d536fc17d56dbe55c487eab01e2ff9382a62598b
67
+ def normalize_uri
68
+ @normalized_uri ||= begin
69
+ uri = @uri.dup
70
+ encoded_query = encode_query(@uri, @options[:query])
71
+ path, query = encoded_query.split("?", 2)
72
+ uri.query = query unless encoded_query.empty?
73
+ uri.path = path
74
+ uri
75
+ end
76
+ end
77
+
78
+ protected
79
+
80
+ def combine_query(path, query, uri_query)
81
+ combined_query = if query.kind_of?(Hash)
82
+ query.map { |k, v| encode_param(k, v) }.join('&')
83
+ else
84
+ query.to_s
85
+ end
86
+ if !uri_query.to_s.empty?
87
+ combined_query = [combined_query, uri_query].reject {|part| part.empty?}.join("&")
88
+ end
89
+ combined_query.to_s.empty? ? path : "#{path}?#{combined_query}"
90
+ end
91
+
92
+ # Since we expect to get the host etc details from the http instance (...),
93
+ # we create a fake url here. Surely this is a horrible, horrible idea?
94
+ def normalized_oauth_uri(http)
95
+ uri = URI.parse(normalize_uri.path)
96
+ uri.host = http.address
97
+ uri.port = http.port
98
+
99
+ if http.respond_to?(:use_ssl?) && http.use_ssl?
100
+ uri.scheme = "https"
101
+ else
102
+ uri.scheme = "http"
103
+ end
104
+ uri.to_s
105
+ end
106
+
107
+ def set_oauth_header
108
+ headers = (self.options[:head] ||= {})
109
+ headers['Authorization'] = @oauth_helper.header
110
+ end
111
+
112
+ def set_oauth_body
113
+ raise NotImplementedError, 'please use the set_oauth_header method instead'
114
+ end
115
+
116
+ def set_oauth_query_string
117
+ raise NotImplementedError, 'please use the set_oauth_header method instead'
118
+ end
119
+
120
+ end
@@ -0,0 +1,91 @@
1
+ require 'oauth/client'
2
+ require 'oauth/consumer'
3
+ require 'oauth/helper'
4
+ require 'oauth/token'
5
+ require 'oauth/signature/hmac/sha1'
6
+
7
+ module OAuth::Client
8
+ class Helper
9
+ include OAuth::Helper
10
+
11
+ def initialize(request, options = {})
12
+ @request = request
13
+ @options = options
14
+ @options[:signature_method] ||= 'HMAC-SHA1'
15
+ end
16
+
17
+ def options
18
+ @options
19
+ end
20
+
21
+ def nonce
22
+ options[:nonce] ||= generate_key
23
+ end
24
+
25
+ def timestamp
26
+ options[:timestamp] ||= generate_timestamp
27
+ end
28
+
29
+ def oauth_parameters
30
+ {
31
+ 'oauth_body_hash' => options[:body_hash],
32
+ 'oauth_callback' => options[:oauth_callback],
33
+ 'oauth_consumer_key' => options[:consumer].key,
34
+ 'oauth_token' => options[:token] ? options[:token].token : '',
35
+ 'oauth_signature_method' => options[:signature_method],
36
+ 'oauth_timestamp' => timestamp,
37
+ 'oauth_nonce' => nonce,
38
+ 'oauth_verifier' => options[:oauth_verifier],
39
+ 'oauth_version' => (options[:oauth_version] || '1.0'),
40
+ 'oauth_session_handle' => options[:oauth_session_handle]
41
+ }.reject { |k,v| v.to_s == "" }
42
+ end
43
+
44
+ def signature(extra_options = {})
45
+ OAuth::Signature.sign(@request, { :uri => options[:request_uri],
46
+ :consumer => options[:consumer],
47
+ :token => options[:token],
48
+ :unsigned_parameters => options[:unsigned_parameters]
49
+ }.merge(extra_options) )
50
+ end
51
+
52
+ def signature_base_string(extra_options = {})
53
+ OAuth::Signature.signature_base_string(@request, { :uri => options[:request_uri],
54
+ :consumer => options[:consumer],
55
+ :token => options[:token],
56
+ :parameters => oauth_parameters}.merge(extra_options) )
57
+ end
58
+
59
+ def hash_body
60
+ @options[:body_hash] = OAuth::Signature.body_hash(@request, :parameters => oauth_parameters)
61
+ end
62
+
63
+ def amend_user_agent_header(headers)
64
+ @oauth_ua_string ||= "OAuth gem v#{OAuth::VERSION}"
65
+ # Net::HTTP in 1.9 appends Ruby
66
+ if headers['User-Agent'] && headers['User-Agent'] != 'Ruby'
67
+ headers['User-Agent'] += " (#{@oauth_ua_string})"
68
+ else
69
+ headers['User-Agent'] = @oauth_ua_string
70
+ end
71
+ end
72
+
73
+ def header
74
+ parameters = oauth_parameters
75
+ parameters.merge!('oauth_signature' => signature(options.merge(:parameters => parameters)))
76
+
77
+ header_params_str = parameters.sort.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
78
+
79
+ realm = "realm=\"#{options[:realm]}\", " if options[:realm]
80
+ "OAuth #{realm}#{header_params_str}"
81
+ end
82
+
83
+ def parameters
84
+ OAuth::RequestProxy.proxy(@request).parameters
85
+ end
86
+
87
+ def parameters_with_oauth
88
+ oauth_parameters.merge(parameters)
89
+ end
90
+ end
91
+ end