monkeyhelper-oauth 0.3.1 → 0.3.5

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 (54) hide show
  1. data/History.txt +62 -17
  2. data/Manifest.txt +14 -1
  3. data/README.rdoc +7 -9
  4. data/Rakefile +7 -5
  5. data/TODO +17 -0
  6. data/bin/oauth +2 -2
  7. data/examples/yql.rb +44 -0
  8. data/lib/oauth/cli.rb +267 -31
  9. data/lib/oauth/client/action_controller_request.rb +14 -12
  10. data/lib/oauth/client/helper.rb +22 -14
  11. data/lib/oauth/client/net_http.rb +53 -22
  12. data/lib/oauth/consumer.rb +217 -111
  13. data/lib/oauth/errors/error.rb +4 -0
  14. data/lib/oauth/errors/problem.rb +14 -0
  15. data/lib/oauth/errors/unauthorized.rb +12 -0
  16. data/lib/oauth/errors.rb +3 -0
  17. data/lib/oauth/helper.rb +67 -6
  18. data/lib/oauth/oauth.rb +11 -0
  19. data/lib/oauth/oauth_test_helper.rb +12 -13
  20. data/lib/oauth/request_proxy/action_controller_request.rb +8 -8
  21. data/lib/oauth/request_proxy/base.rb +102 -44
  22. data/lib/oauth/request_proxy/jabber_request.rb +1 -2
  23. data/lib/oauth/request_proxy/mock_request.rb +8 -0
  24. data/lib/oauth/request_proxy/net_http.rb +2 -2
  25. data/lib/oauth/request_proxy/rack_request.rb +7 -7
  26. data/lib/oauth/server.rb +31 -33
  27. data/lib/oauth/signature/base.rb +23 -21
  28. data/lib/oauth/signature/hmac/base.rb +1 -1
  29. data/lib/oauth/signature/hmac/sha1.rb +0 -1
  30. data/lib/oauth/signature/plaintext.rb +2 -2
  31. data/lib/oauth/signature/rsa/sha1.rb +5 -4
  32. data/lib/oauth/signature.rb +9 -0
  33. data/lib/oauth/token.rb +6 -136
  34. data/lib/oauth/tokens/access_token.rb +68 -0
  35. data/lib/oauth/tokens/consumer_token.rb +33 -0
  36. data/lib/oauth/tokens/request_token.rb +32 -0
  37. data/lib/oauth/tokens/server_token.rb +9 -0
  38. data/lib/oauth/tokens/token.rb +17 -0
  39. data/lib/oauth/version.rb +1 -1
  40. data/lib/oauth.rb +1 -0
  41. data/oauth.gemspec +12 -6
  42. data/test/cases/spec/1_0-final/test_construct_request_url.rb +1 -1
  43. data/test/test_access_token.rb +28 -0
  44. data/test/test_action_controller_request_proxy.rb +105 -6
  45. data/test/test_consumer.rb +41 -5
  46. data/test/test_helper.rb +0 -5
  47. data/test/test_net_http_client.rb +38 -20
  48. data/test/test_net_http_request_proxy.rb +43 -8
  49. data/test/test_oauth_helper.rb +50 -0
  50. data/test/test_request_token.rb +53 -0
  51. data/test/test_server.rb +1 -1
  52. data/test/test_signature.rb +19 -11
  53. data/website/index.html +2 -2
  54. metadata +41 -3
@@ -1,19 +1,32 @@
1
1
  require 'net/http'
2
2
  require 'net/https'
3
+ require 'oauth/oauth'
3
4
  require 'oauth/client/net_http'
5
+ require 'oauth/errors'
6
+
4
7
  module OAuth
5
8
  class Consumer
6
-
7
- @@default_options={
9
+ # determine the certificate authority path to verify SSL certs
10
+ CA_FILES = %w(/etc/ssl/certs/ca-certificates.crt /usr/share/curl/curl-ca-bundle.crt)
11
+ CA_FILES.each do |ca_file|
12
+ if File.exists?(ca_file)
13
+ CA_FILE = ca_file
14
+ break
15
+ end
16
+ end
17
+ CA_FILE = nil unless defined?(CA_FILE)
18
+
19
+ @@default_options = {
8
20
  # Signature method used by server. Defaults to HMAC-SHA1
9
- :signature_method => 'HMAC-SHA1',
10
-
21
+ :signature_method => 'HMAC-SHA1',
22
+
11
23
  # default paths on site. These are the same as the defaults set up by the generators
12
- :request_token_path=>'/oauth/request_token',
13
- :authorize_path=>'/oauth/authorize',
14
- :access_token_path=>'/oauth/access_token',
15
-
16
- # How do we send the oauth values to the server see
24
+ :request_token_path => '/oauth/request_token',
25
+ :authorize_path => '/oauth/authorize',
26
+ :access_token_path => '/oauth/access_token',
27
+
28
+ :proxy => nil,
29
+ # How do we send the oauth values to the server see
17
30
  # http://oauth.net/core/1.0/#consumer_req_param for more info
18
31
  #
19
32
  # Possible values:
@@ -21,123 +34,179 @@ module OAuth
21
34
  # :header - via the Authorize header (Default) ( option 1. in spec)
22
35
  # :body - url form encoded in body of POST request ( option 2. in spec)
23
36
  # :query_string - via the query part of the url ( option 3. in spec)
24
- :scheme=>:header,
25
-
37
+ :scheme => :header,
38
+
26
39
  # Default http method used for OAuth Token Requests (defaults to :post)
27
- :http_method=>:post,
28
-
29
- :oauth_version=>"1.0"
40
+ :http_method => :post,
41
+
42
+ :oauth_version => "1.0"
30
43
  }
31
-
32
- attr_accessor :site,:options, :key, :secret,:http
33
-
34
-
44
+
45
+ attr_accessor :options, :key, :secret
46
+ attr_writer :site, :http
47
+
35
48
  # Create a new consumer instance by passing it a configuration hash:
36
49
  #
37
- # @consumer=OAuth::Consumer.new( key,secret,{
38
- # :site=>"http://term.ie",
39
- # :scheme=>:header,
40
- # :http_method=>:post,
41
- # :request_token_path=>"/oauth/example/request_token.php",
42
- # :access_token_path=>"/oauth/example/access_token.php",
43
- # :authorize_path=>"/oauth/example/authorize.php"
50
+ # @consumer = OAuth::Consumer.new(key, secret, {
51
+ # :site => "http://term.ie",
52
+ # :scheme => :header,
53
+ # :http_method => :post,
54
+ # :request_token_path => "/oauth/example/request_token.php",
55
+ # :access_token_path => "/oauth/example/access_token.php",
56
+ # :authorize_path => "/oauth/example/authorize.php"
44
57
  # })
45
58
  #
46
59
  # Start the process by requesting a token
47
60
  #
48
- # @request_token=@consumer.get_request_token
49
- # session[:request_token]=@request_token
61
+ # @request_token = @consumer.get_request_token
62
+ # session[:request_token] = @request_token
50
63
  # redirect_to @request_token.authorize_url
51
64
  #
52
65
  # When user returns create an access_token
53
66
  #
54
- # @access_token=@request_token.get_access_token
67
+ # @access_token = @request_token.get_access_token
55
68
  # @photos=@access_token.get('/photos.xml')
56
69
  #
57
- #
58
-
59
- def initialize(consumer_key,consumer_secret,options={})
70
+ def initialize(consumer_key, consumer_secret, options = {})
71
+ @key = consumer_key
72
+ @secret = consumer_secret
73
+
60
74
  # ensure that keys are symbols
61
- @options=@@default_options.merge( options.inject({}) do |options, (key, value)|
75
+ @options = @@default_options.merge(options.inject({}) { |options, (key, value)|
62
76
  options[key.to_sym] = value
63
77
  options
64
- end)
65
- @key = consumer_key
66
- @secret = consumer_secret
78
+ })
67
79
  end
68
-
80
+
69
81
  # The default http method
70
82
  def http_method
71
- @http_method||=@options[:http_method]||:post
83
+ @http_method ||= @options[:http_method] || :post
72
84
  end
73
-
85
+
74
86
  # The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
75
87
  def http
76
88
  @http ||= create_http
77
89
  end
78
-
90
+
79
91
  # Contains the root URI for this site
80
- def uri(custom_uri=nil)
92
+ def uri(custom_uri = nil)
81
93
  if custom_uri
82
- @uri = custom_uri
94
+ @uri = custom_uri
83
95
  @http = create_http # yike, oh well. less intrusive this way
84
96
  else # if no custom passed, we use existing, which, if unset, is set to site uri
85
97
  @uri ||= URI.parse(site)
86
98
  end
87
99
  end
88
-
100
+
101
+ def get_access_token(request_token, request_options = {}, *arguments)
102
+ response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token, request_options, *arguments)
103
+ OAuth::AccessToken.from_hash(self, response)
104
+ end
105
+
89
106
  # Makes a request to the service for a new OAuth::RequestToken
90
- #
91
- # @request_token=@consumer.get_request_token
92
107
  #
93
- def get_request_token(request_options={}, *arguments)
94
- response=token_request(http_method,(request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
95
- OAuth::RequestToken.new(self,response[:oauth_token],response[:oauth_token_secret])
108
+ # @request_token = @consumer.get_request_token
109
+ #
110
+ # To include OAuth parameters:
111
+ #
112
+ # @request_token = @consumer.get_request_token \
113
+ # :oauth_callback => "http://example.com/cb"
114
+ #
115
+ # To include application-specific parameters:
116
+ #
117
+ # @request_token = @consumer.get_request_token({}, :foo => "bar")
118
+ #
119
+ # TODO oauth_callback should be a mandatory parameter
120
+ def get_request_token(request_options = {}, *arguments)
121
+ # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
122
+ # will be exchanged out of band
123
+ request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND
124
+
125
+ response = token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
126
+ OAuth::RequestToken.from_hash(self, response)
96
127
  end
97
-
128
+
98
129
  # Creates, signs and performs an http request.
99
130
  # It's recommended to use the OAuth::Token classes to set this up correctly.
100
- # The arguments parameters are a hash or string encoded set of parameters if it's a post request as well as optional http headers.
101
- #
102
- # @consumer.request(:get,'/people',@token,{:scheme=>:query_string})
103
- # @consumer.request(:post,'/people',@token,{},@person.to_xml,{ 'Content-Type' => 'application/xml' })
131
+ # request_options take precedence over consumer-wide options when signing
132
+ # a request.
133
+ # arguments are POST and PUT bodies (a Hash, string-encoded parameters, or
134
+ # absent), followed by additional HTTP headers.
104
135
  #
105
- def request(http_method,path, token=nil,request_options={},*arguments)
106
- if path=~/^\//
107
- _http=http
108
- else
109
- _http=create_http(path)
110
- _uri=URI.parse(path)
111
- path="#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
136
+ # @consumer.request(:get, '/people', @token, { :scheme => :query_string })
137
+ # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
138
+ #
139
+ def request(http_method, path, token = nil, request_options = {}, *arguments)
140
+ if path !~ /^\//
141
+ @http = create_http(path)
142
+ _uri = URI.parse(path)
143
+ path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
112
144
  end
113
- _http.request(create_signed_request(http_method,path,token,request_options,*arguments))
145
+
146
+ rsp = http.request(create_signed_request(http_method, path, token, request_options, *arguments))
147
+
148
+ # check for an error reported by the Problem Reporting extension
149
+ # (http://wiki.oauth.net/ProblemReporting)
150
+ # note: a 200 may actually be an error; check for an oauth_problem key to be sure
151
+ if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
152
+ (h = headers.select { |h| h =~ /^OAuth / }).any? &&
153
+ h.first =~ /oauth_problem/
154
+
155
+ # puts "Header: #{h.first}"
156
+
157
+ # TODO doesn't handle broken responses from api.login.yahoo.com
158
+ # remove debug code when done
159
+ params = OAuth::Helper.parse_header(h.first)
160
+
161
+ # puts "Params: #{params.inspect}"
162
+ # puts "Body: #{rsp.body}"
163
+
164
+ raise OAuth::Problem.new(params.delete("oauth_problem"), rsp, params)
165
+ end
166
+
167
+ rsp
114
168
  end
115
-
169
+
116
170
  # Creates and signs an http request.
117
171
  # It's recommended to use the Token classes to set this up correctly
118
- def create_signed_request(http_method,path, token=nil,request_options={},*arguments)
119
- request=create_http_request(http_method,path,*arguments)
120
- sign!(request,token,request_options)
172
+ def create_signed_request(http_method, path, token = nil, request_options = {}, *arguments)
173
+ request = create_http_request(http_method, path, *arguments)
174
+ sign!(request, token, request_options)
121
175
  request
122
176
  end
123
-
177
+
124
178
  # Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
125
- def token_request(http_method,path,token=nil,request_options={},*arguments)
126
- response=request(http_method,path,token,request_options,*arguments)
127
- if response.code=="200"
128
- CGI.parse(response.body).inject({}){|h,(k,v)| h[k.to_sym]=v.first;h}
129
- else
130
- response.error!
179
+ def token_request(http_method, path, token = nil, request_options = {}, *arguments)
180
+ response = request(http_method, path, token, request_options, *arguments)
181
+
182
+ case response.code.to_i
183
+
184
+ when (200..299)
185
+ # symbolize keys
186
+ # TODO this could be considered unexpected behavior; symbols or not?
187
+ # TODO this also drops subsequent values from multi-valued keys
188
+ CGI.parse(response.body).inject({}) do |h,(k,v)|
189
+ h[k.to_sym] = v.first
190
+ h[k] = v.first
191
+ h
192
+ end
193
+ when (300..399)
194
+ # this is a redirect
195
+ response.error!
196
+ when (400..499)
197
+ raise OAuth::Unauthorized, response
198
+ else
199
+ response.error!
131
200
  end
132
201
  end
133
202
 
134
203
  # Sign the Request object. Use this if you have an externally generated http request object you want to sign.
135
- def sign!(request,token=nil, request_options = {})
204
+ def sign!(request, token = nil, request_options = {})
136
205
  request.oauth!(http, self, token, options.merge(request_options))
137
206
  end
138
-
207
+
139
208
  # Return the signature_base_string
140
- def signature_base_string(request,token=nil, request_options = {})
209
+ def signature_base_string(request, token = nil, request_options = {})
141
210
  request.signature_base_string(http, self, token, options.merge(request_options))
142
211
  end
143
212
 
@@ -148,90 +217,127 @@ module OAuth
148
217
  def scheme
149
218
  @options[:scheme]
150
219
  end
151
-
220
+
152
221
  def request_token_path
153
222
  @options[:request_token_path]
154
223
  end
155
-
224
+
156
225
  def authorize_path
157
226
  @options[:authorize_path]
158
227
  end
159
-
228
+
160
229
  def access_token_path
161
230
  @options[:access_token_path]
162
231
  end
163
-
232
+
164
233
  # TODO this is ugly, rewrite
165
234
  def request_token_url
166
- @options[:request_token_url]||site+request_token_path
235
+ @options[:request_token_url] || site + request_token_path
167
236
  end
168
237
 
169
238
  def request_token_url?
170
- @options[:request_token_url]!=nil
239
+ @options.has_key?(:request_token_url)
171
240
  end
172
-
241
+
173
242
  def authorize_url
174
- @options[:authorize_url]||site+authorize_path
243
+ @options[:authorize_url] || site + authorize_path
175
244
  end
176
-
245
+
177
246
  def authorize_url?
178
- @options[:authorize_url]!=nil
247
+ @options.has_key?(:authorize_url)
179
248
  end
180
249
 
181
250
  def access_token_url
182
- @options[:access_token_url]||site+access_token_path
251
+ @options[:access_token_url] || site + access_token_path
183
252
  end
184
253
 
185
254
  def access_token_url?
186
- @options[:access_token_url]!=nil
255
+ @options.has_key?(:access_token_url)
256
+ end
257
+
258
+ def proxy
259
+ @options[:proxy]
187
260
  end
188
261
 
189
- protected
190
-
191
- #Instantiates the http object
192
- def create_http(_url=nil)
193
- if _url.nil?||_url[0]=~/^\//
194
- our_uri=URI.parse(site)
262
+ protected
263
+
264
+ # Instantiates the http object
265
+ def create_http(_url = nil)
266
+ if _url.nil? || _url[0] =~ /^\//
267
+ our_uri = URI.parse(site)
268
+ else
269
+ our_uri = URI.parse(_url)
270
+ end
271
+
272
+ if proxy.nil?
273
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port)
274
+ else
275
+ proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
276
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
277
+ end
278
+
279
+ http_object.use_ssl = (our_uri.scheme == 'https')
280
+
281
+ if CA_FILE
282
+ http_object.ca_file = CA_FILE
283
+ http_object.verify_mode = OpenSSL::SSL::VERIFY_PEER
284
+ http_object.verify_depth = 5
195
285
  else
196
- our_uri=URI.parse(_url)
286
+ http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE
197
287
  end
198
- http_object=Net::HTTP.new(our_uri.host, our_uri.port)
199
- http_object.use_ssl = true if our_uri.scheme=="https"
288
+
200
289
  http_object
201
290
  end
202
-
291
+
203
292
  # create the http request object for a given http_method and path
204
- def create_http_request(http_method,path,*arguments)
205
- http_method=http_method.to_sym
206
- if [:post,:put].include?(http_method)
207
- data=arguments.shift
293
+ def create_http_request(http_method, path, *arguments)
294
+ http_method = http_method.to_sym
295
+
296
+ if [:post, :put].include?(http_method)
297
+ data = arguments.shift
298
+ data = {} if data.nil?
208
299
  end
209
- headers=(arguments.first.is_a?(Hash) ? arguments.shift : {})
300
+
301
+ headers = arguments.first.is_a?(Hash) ? arguments.first.reject { |k,v| v.nil? } : {}
302
+
210
303
  case http_method
211
304
  when :post
212
- request=Net::HTTP::Post.new(path,headers)
213
- request["Content-Length"]=0 # Default to 0
305
+ request = Net::HTTP::Post.new(path,headers)
306
+ request["Content-Length"] = 0 # Default to 0
214
307
  when :put
215
- request=Net::HTTP::Put.new(path,headers)
216
- request["Content-Length"]=0 # Default to 0
308
+ request = Net::HTTP::Put.new(path,headers)
309
+ request["Content-Length"] = 0 # Default to 0
217
310
  when :get
218
- request=Net::HTTP::Get.new(path,headers)
311
+ request = Net::HTTP::Get.new(path,headers)
219
312
  when :delete
220
- request=Net::HTTP::Delete.new(path,headers)
313
+ request = Net::HTTP::Delete.new(path,headers)
221
314
  when :head
222
- request=Net::HTTP::Head.new(path,headers)
315
+ request = Net::HTTP::Head.new(path,headers)
223
316
  else
224
317
  raise ArgumentError, "Don't know how to handle http_method: :#{http_method.to_s}"
225
318
  end
319
+
226
320
  if data.is_a?(Hash)
227
321
  request.set_form_data(data)
228
322
  elsif data
229
- request.body=data.to_s
230
- request["Content-Length"]=request.body.length
323
+ if data.respond_to?(:read)
324
+ request.body_stream = data
325
+ if data.respond_to?(:length)
326
+ request["Content-Length"] = data.length
327
+ elsif data.respond_to?(:stat) && data.stat.respond_to?(:size)
328
+ request["Content-Length"] = data.stat.size
329
+ else
330
+ raise ArgumentError, "Don't know how to send a body_stream that doesn't respond to .length or .stat.size"
331
+ end
332
+ else
333
+ request.body = data.to_s
334
+ request["Content-Length"] = request.body.length
335
+ end
231
336
  end
337
+
232
338
  request
233
339
  end
234
-
340
+
235
341
  # Unset cached http instance because it cannot be marshalled when
236
342
  # it has already been used and use_ssl is set to true
237
343
  def marshal_dump(*args)
@@ -0,0 +1,4 @@
1
+ module OAuth
2
+ class Error < StandardError
3
+ end
4
+ end
@@ -0,0 +1,14 @@
1
+ module OAuth
2
+ class Problem < OAuth::Unauthorized
3
+ attr_reader :problem, :params
4
+ def initialize(problem, request = nil, params = {})
5
+ super(request)
6
+ @problem = problem
7
+ @params = params
8
+ end
9
+
10
+ def to_s
11
+ problem
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ module OAuth
2
+ class Unauthorized < OAuth::Error
3
+ attr_reader :request
4
+ def initialize(request = nil)
5
+ @request = request
6
+ end
7
+
8
+ def to_s
9
+ [request.code, request.message] * " "
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ require 'oauth/errors/error'
2
+ require 'oauth/errors/unauthorized'
3
+ require 'oauth/errors/problem'
data/lib/oauth/helper.rb CHANGED
@@ -1,17 +1,78 @@
1
1
  require 'openssl'
2
2
  require 'base64'
3
- require 'cgi'
3
+
4
4
  module OAuth
5
5
  module Helper
6
6
  extend self
7
7
 
8
+ # Escape +value+ by URL encoding all non-reserved character.
9
+ #
10
+ # See Also: {OAuth core spec version 1.0, section 5.1}[http://oauth.net/core/1.0#rfc.section.5.1]
8
11
  def escape(value)
9
- CGI.escape(value.to_s).gsub("%7E", '~').gsub("+", "%20")
12
+ URI::escape(value.to_s, OAuth::RESERVED_CHARACTERS)
10
13
  end
11
-
14
+
15
+ # Generate a random key of up to +size+ bytes. The value returned is Base64 encoded with non-word
16
+ # characters removed.
12
17
  def generate_key(size=32)
13
- Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/,'')
14
- end
15
-
18
+ Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, '')
19
+ end
20
+
21
+ alias_method :generate_nonce, :generate_key
22
+
23
+ def generate_timestamp #:nodoc:
24
+ Time.now.to_i.to_s
25
+ end
26
+
27
+ # Normalize a +Hash+ of parameter values. Parameters are sorted by name, using lexicographical
28
+ # byte value ordering. If two or more parameters share the same name, they are sorted by their value.
29
+ # Parameters are concatenated in their sorted order into a single string. For each parameter, the name
30
+ # is separated from the corresponding value by an "=" character, even if the value is empty. Each
31
+ # name-value pair is separated by an "&" character.
32
+ #
33
+ # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
34
+ def normalize(params)
35
+ params.sort.map do |k, values|
36
+
37
+ if values.is_a?(Array)
38
+ # multiple values were provided for a single key
39
+ values.sort.collect do |v|
40
+ [escape(k),escape(v)] * "="
41
+ end
42
+ else
43
+ [escape(k),escape(values)] * "="
44
+ end
45
+ end * "&"
46
+ end
47
+
48
+ # Parse an Authorization / WWW-Authenticate header into a hash. Takes care of unescaping and
49
+ # removing surrounding quotes. Raises a OAuth::Problem if the header is not parsable into a
50
+ # valid hash. Does not validate the keys or values.
51
+ #
52
+ # hash = parse_header(headers['Authorization'] || headers['WWW-Authenticate'])
53
+ # hash['oauth_timestamp']
54
+ # #=>"1234567890"
55
+ #
56
+ def parse_header(header)
57
+ # decompose
58
+ params = header[6,header.length].split(/[,=]/)
59
+
60
+ # odd number of arguments - must be a malformed header.
61
+ raise OAuth::Problem.new("Invalid authorization header") if params.size % 2 != 0
62
+
63
+ params.map! do |v|
64
+ # strip and unescape
65
+ val = unescape(v.strip)
66
+ # strip quotes
67
+ val.sub(/^\"(.*)\"$/, '\1')
68
+ end
69
+
70
+ # convert into a Hash
71
+ Hash[*params.flatten]
72
+ end
73
+
74
+ def unescape(value)
75
+ URI.unescape(value.gsub('+', '%2B'))
76
+ end
16
77
  end
17
78
  end
@@ -0,0 +1,11 @@
1
+ module OAuth
2
+ # request tokens are passed between the consumer and the provider out of
3
+ # band (i.e. callbacks cannot be used), per section 6.1.1
4
+ OUT_OF_BAND = "oob"
5
+
6
+ # required parameters, per sections 6.1.1, 6.3.1, and 7
7
+ PARAMETERS = %w(oauth_callback oauth_consumer_key oauth_token oauth_signature_method oauth_timestamp oauth_nonce oauth_verifier oauth_version oauth_signature)
8
+
9
+ # reserved character regexp, per section 5.1
10
+ RESERVED_CHARACTERS = /[^a-zA-Z0-9\-\.\_\~]/
11
+ end
@@ -1,26 +1,25 @@
1
1
  require 'action_controller'
2
2
  require 'action_controller/test_process'
3
+
3
4
  module OAuth
4
5
  module OAuthTestHelper
5
-
6
6
  def mock_incoming_request_with_query(request)
7
- incoming=ActionController::TestRequest.new(request.to_hash)
8
- incoming.request_uri=request.path
9
- incoming.env["SERVER_PORT"]=request.uri.port
10
- incoming.host=request.uri.host
11
- incoming.env['REQUEST_METHOD']=request.http_method
7
+ incoming = ActionController::TestRequest.new(request.to_hash)
8
+ incoming.request_uri = request.path
9
+ incoming.host = request.uri.host
10
+ incoming.env["SERVER_PORT"] = request.uri.port
11
+ incoming.env['REQUEST_METHOD'] = request.http_method
12
12
  incoming
13
13
  end
14
14
 
15
15
  def mock_incoming_request_with_authorize_header(request)
16
- incoming=ActionController::TestRequest.new
17
- incoming.env["HTTP_AUTHORIZATION"]=request.to_auth_string
18
- incoming.request_uri=request.path
19
- incoming.env["SERVER_PORT"]=request.uri.port
20
- incoming.host=request.uri.host
21
- incoming.env['REQUEST_METHOD']=request.http_method
16
+ incoming = ActionController::TestRequest.new
17
+ incoming.request_uri = request.path
18
+ incoming.host = request.uri.host
19
+ incoming.env["HTTP_AUTHORIZATION"] = request.to_auth_string
20
+ incoming.env["SERVER_PORT"] = request.uri.port
21
+ incoming.env['REQUEST_METHOD'] = request.http_method
22
22
  incoming
23
23
  end
24
-
25
24
  end
26
25
  end
@@ -1,5 +1,5 @@
1
- require 'rubygems'
2
1
  require 'active_support'
2
+ require 'action_controller'
3
3
  require 'action_controller/request'
4
4
  require 'oauth/request_proxy/base'
5
5
  require 'uri'
@@ -25,7 +25,7 @@ module OAuth::RequestProxy
25
25
  params.merge(options[:parameters] || {})
26
26
  end
27
27
  end
28
-
28
+
29
29
  # Override from OAuth::RequestProxy::Base to avoid roundtrip
30
30
  # conversion to Hash or Array and thus preserve the original
31
31
  # parameter names
@@ -36,19 +36,19 @@ module OAuth::RequestProxy
36
36
  unless options[:clobber_request]
37
37
  params << header_params.to_query
38
38
  params << request.query_string unless request.query_string.blank?
39
- if request.content_type == Mime::Type.lookup("application/x-www-form-urlencoded")
40
- params << CGI.unescape(request.raw_post)
39
+ if request.post? && request.content_type == Mime::Type.lookup("application/x-www-form-urlencoded")
40
+ params << request.raw_post
41
41
  end
42
42
  end
43
-
43
+
44
44
  params.
45
45
  join('&').split('&').
46
- reject { |kv| kv =~ /^oauth_signature=.*/}.
47
46
  reject(&:blank?).
48
- map { |p| p.split('=') }
47
+ map { |p| p.split('=').map{|esc| CGI.unescape(esc)} }.
48
+ reject { |kv| kv[0] == 'oauth_signature'}
49
49
  end
50
50
 
51
- protected
51
+ protected
52
52
 
53
53
  def query_params
54
54
  request.query_parameters