metavida-oauth 0.3.2

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 (84) hide show
  1. data/History.txt +66 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +83 -0
  4. data/README.rdoc +71 -0
  5. data/Rakefile +36 -0
  6. data/TODO +32 -0
  7. data/bin/oauth +5 -0
  8. data/examples/yql.rb +44 -0
  9. data/lib/oauth/cli.rb +300 -0
  10. data/lib/oauth/client/action_controller_request.rb +53 -0
  11. data/lib/oauth/client/helper.rb +71 -0
  12. data/lib/oauth/client/net_http.rb +78 -0
  13. data/lib/oauth/client.rb +4 -0
  14. data/lib/oauth/consumer.rb +296 -0
  15. data/lib/oauth/errors/error.rb +4 -0
  16. data/lib/oauth/errors/problem.rb +14 -0
  17. data/lib/oauth/errors/unauthorized.rb +12 -0
  18. data/lib/oauth/errors.rb +3 -0
  19. data/lib/oauth/helper.rb +55 -0
  20. data/lib/oauth/oauth.rb +7 -0
  21. data/lib/oauth/oauth_test_helper.rb +25 -0
  22. data/lib/oauth/request_proxy/action_controller_request.rb +68 -0
  23. data/lib/oauth/request_proxy/base.rb +157 -0
  24. data/lib/oauth/request_proxy/jabber_request.rb +41 -0
  25. data/lib/oauth/request_proxy/mock_request.rb +44 -0
  26. data/lib/oauth/request_proxy/net_http.rb +65 -0
  27. data/lib/oauth/request_proxy/rack_request.rb +40 -0
  28. data/lib/oauth/request_proxy.rb +24 -0
  29. data/lib/oauth/server.rb +66 -0
  30. data/lib/oauth/signature/base.rb +91 -0
  31. data/lib/oauth/signature/hmac/base.rb +12 -0
  32. data/lib/oauth/signature/hmac/md5.rb +9 -0
  33. data/lib/oauth/signature/hmac/rmd160.rb +9 -0
  34. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  35. data/lib/oauth/signature/hmac/sha2.rb +9 -0
  36. data/lib/oauth/signature/md5.rb +13 -0
  37. data/lib/oauth/signature/plaintext.rb +23 -0
  38. data/lib/oauth/signature/rsa/sha1.rb +45 -0
  39. data/lib/oauth/signature/sha1.rb +13 -0
  40. data/lib/oauth/signature.rb +28 -0
  41. data/lib/oauth/token.rb +7 -0
  42. data/lib/oauth/tokens/access_token.rb +68 -0
  43. data/lib/oauth/tokens/consumer_token.rb +32 -0
  44. data/lib/oauth/tokens/request_token.rb +28 -0
  45. data/lib/oauth/tokens/server_token.rb +9 -0
  46. data/lib/oauth/tokens/token.rb +17 -0
  47. data/lib/oauth/version.rb +3 -0
  48. data/lib/oauth.rb +4 -0
  49. data/oauth.gemspec +49 -0
  50. data/script/destroy +14 -0
  51. data/script/generate +14 -0
  52. data/script/txt2html +74 -0
  53. data/setup.rb +1585 -0
  54. data/tasks/deployment.rake +34 -0
  55. data/tasks/environment.rake +7 -0
  56. data/tasks/website.rake +17 -0
  57. data/test/cases/oauth_case.rb +19 -0
  58. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  59. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  60. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  61. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  62. data/test/keys/rsa.cert +11 -0
  63. data/test/keys/rsa.pem +16 -0
  64. data/test/test_access_token.rb +28 -0
  65. data/test/test_action_controller_request_proxy.rb +45 -0
  66. data/test/test_consumer.rb +327 -0
  67. data/test/test_helper.rb +11 -0
  68. data/test/test_hmac_sha1.rb +21 -0
  69. data/test/test_net_http_client.rb +169 -0
  70. data/test/test_net_http_request_proxy.rb +38 -0
  71. data/test/test_rack_request_proxy.rb +40 -0
  72. data/test/test_request_token.rb +53 -0
  73. data/test/test_rsa_sha1.rb +59 -0
  74. data/test/test_server.rb +40 -0
  75. data/test/test_signature.rb +11 -0
  76. data/test/test_signature_base.rb +32 -0
  77. data/test/test_signature_plain_text.rb +31 -0
  78. data/test/test_token.rb +14 -0
  79. data/website/index.html +87 -0
  80. data/website/index.txt +73 -0
  81. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  82. data/website/stylesheets/screen.css +138 -0
  83. data/website/template.rhtml +48 -0
  84. metadata +212 -0
@@ -0,0 +1,53 @@
1
+ require 'oauth/client/helper'
2
+ require 'oauth/request_proxy/action_controller_request'
3
+ require 'action_controller/test_process'
4
+
5
+ module ActionController
6
+ class Base
7
+ def process_with_oauth(request, response=nil)
8
+ request.apply_oauth!
9
+ process_without_oauth(request, response)
10
+ end
11
+
12
+ alias_method_chain :process, :oauth
13
+ end
14
+
15
+ class TestRequest
16
+ def self.use_oauth=(bool)
17
+ @use_oauth = bool
18
+ end
19
+
20
+ def self.use_oauth?
21
+ @use_oauth
22
+ end
23
+
24
+ def configure_oauth(consumer = nil, token = nil, options = {})
25
+ @oauth_options = { :consumer => consumer,
26
+ :token => token,
27
+ :scheme => 'header',
28
+ :signature_method => nil,
29
+ :nonce => nil,
30
+ :timestamp => nil }.merge(options)
31
+ end
32
+
33
+ def apply_oauth!
34
+ return unless ActionController::TestRequest.use_oauth? && @oauth_options
35
+
36
+ @oauth_helper = OAuth::Client::Helper.new(self, @oauth_options.merge(:request_uri => request_uri))
37
+
38
+ self.send("set_oauth_#{@oauth_options[:scheme]}")
39
+ end
40
+
41
+ def set_oauth_header
42
+ env['Authorization'] = @oauth_helper.header
43
+ end
44
+
45
+ def set_oauth_parameters
46
+ @query_parameters = @oauth_helper.parameters_with_oauth
47
+ @query_parameters.merge!(:oauth_signature => @oauth_helper.signature)
48
+ end
49
+
50
+ def set_oauth_query_string
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,71 @@
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_consumer_key' => options[:consumer].key,
32
+ 'oauth_token' => options[:token] ? options[:token].token : '',
33
+ 'oauth_signature_method' => options[:signature_method],
34
+ 'oauth_timestamp' => timestamp,
35
+ 'oauth_nonce' => nonce,
36
+ 'oauth_version' => '1.0'
37
+ }.reject { |k,v| v.to_s == "" }
38
+ end
39
+
40
+ def signature(extra_options = {})
41
+ OAuth::Signature.sign(@request, { :uri => options[:request_uri],
42
+ :consumer => options[:consumer],
43
+ :token => options[:token] }.merge(extra_options) )
44
+ end
45
+
46
+ def signature_base_string(extra_options = {})
47
+ OAuth::Signature.signature_base_string(@request, { :uri => options[:request_uri],
48
+ :consumer => options[:consumer],
49
+ :token => options[:token],
50
+ :parameters => oauth_parameters}.merge(extra_options) )
51
+ end
52
+
53
+ def header
54
+ parameters = oauth_parameters
55
+ parameters.merge!('oauth_signature' => signature(options.merge(:parameters => parameters)))
56
+
57
+ header_params_str = parameters.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
58
+
59
+ realm = "realm=\"#{options[:realm]}\", " if options[:realm]
60
+ "OAuth #{realm}#{header_params_str}"
61
+ end
62
+
63
+ def parameters
64
+ OAuth::RequestProxy.proxy(@request).parameters
65
+ end
66
+
67
+ def parameters_with_oauth
68
+ oauth_parameters.merge(parameters)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,78 @@
1
+ require 'oauth/helper'
2
+ require 'oauth/client/helper'
3
+ require 'oauth/request_proxy/net_http'
4
+
5
+ class Net::HTTPRequest
6
+ include OAuth::Helper
7
+
8
+ attr_reader :oauth_helper
9
+
10
+ def oauth!(http, consumer = nil, token = nil, options = {})
11
+ options = { :request_uri => oauth_full_request_uri(http),
12
+ :consumer => consumer,
13
+ :token => token,
14
+ :scheme => 'header',
15
+ :signature_method => nil,
16
+ :nonce => nil,
17
+ :timestamp => nil }.merge(options)
18
+
19
+ @oauth_helper = OAuth::Client::Helper.new(self, options)
20
+ self.send("set_oauth_#{options[:scheme]}")
21
+ end
22
+
23
+ def signature_base_string(http, consumer = nil, token = nil, options = {})
24
+ options = { :request_uri => oauth_full_request_uri(http),
25
+ :consumer => consumer,
26
+ :token => token,
27
+ :scheme => 'header',
28
+ :signature_method => nil,
29
+ :nonce => nil,
30
+ :timestamp => nil }.merge(options)
31
+
32
+ OAuth::Client::Helper.new(self, options).signature_base_string
33
+ end
34
+
35
+ private
36
+
37
+ def oauth_full_request_uri(http)
38
+ uri = URI.parse(self.path)
39
+ uri.host = http.address
40
+ uri.port = http.port
41
+
42
+ if http.respond_to?(:use_ssl?) && http.use_ssl?
43
+ uri.scheme = "https"
44
+ else
45
+ uri.scheme = "http"
46
+ end
47
+
48
+ uri.to_s
49
+ end
50
+
51
+ def set_oauth_header
52
+ self['Authorization'] = @oauth_helper.header
53
+ end
54
+
55
+ # FIXME: if you're using a POST body and query string parameters, using this
56
+ # method will convert those parameters on the query string into parameters in
57
+ # the body. this is broken, and should be fixed.
58
+ def set_oauth_body
59
+ self.set_form_data(@oauth_helper.parameters_with_oauth)
60
+ params_with_sig = @oauth_helper.parameters.merge(:oauth_signature => @oauth_helper.signature)
61
+ self.set_form_data(params_with_sig)
62
+ end
63
+
64
+ def set_oauth_query_string
65
+ oauth_params_str = @oauth_helper.oauth_parameters.map { |k,v| [escape(k), escape(v)] * "=" }.join("&")
66
+
67
+ uri = URI.parse(path)
68
+ if uri.query.to_s == ""
69
+ uri.query = oauth_params_str
70
+ else
71
+ uri.query = uri.query + "&" + oauth_params_str
72
+ end
73
+
74
+ @path = uri.to_s
75
+
76
+ @path << "&oauth_signature=#{escape(oauth_helper.signature)}"
77
+ end
78
+ end
@@ -0,0 +1,4 @@
1
+ module OAuth
2
+ module Client
3
+ end
4
+ end
@@ -0,0 +1,296 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'oauth/client/net_http'
4
+ require 'oauth/errors'
5
+
6
+ module OAuth
7
+ class Consumer
8
+ # determine the certificate authority path to verify SSL certs
9
+ CA_FILES = %w(/etc/ssl/certs/ca-certificates.crt /usr/share/curl/curl-ca-bundle.crt)
10
+ CA_FILES.each do |ca_file|
11
+ if File.exists?(ca_file)
12
+ CA_FILE = ca_file
13
+ break
14
+ end
15
+ end
16
+ CA_FILE = nil unless defined?(CA_FILE)
17
+
18
+ @@default_options = {
19
+ # Signature method used by server. Defaults to HMAC-SHA1
20
+ :signature_method => 'HMAC-SHA1',
21
+
22
+ # default paths on site. These are the same as the defaults set up by the generators
23
+ :request_token_path => '/oauth/request_token',
24
+ :authorize_path => '/oauth/authorize',
25
+ :access_token_path => '/oauth/access_token',
26
+
27
+ # How do we send the oauth values to the server see
28
+ # http://oauth.net/core/1.0/#consumer_req_param for more info
29
+ #
30
+ # Possible values:
31
+ #
32
+ # :header - via the Authorize header (Default) ( option 1. in spec)
33
+ # :body - url form encoded in body of POST request ( option 2. in spec)
34
+ # :query_string - via the query part of the url ( option 3. in spec)
35
+ :scheme => :header,
36
+
37
+ # Default http method used for OAuth Token Requests (defaults to :post)
38
+ :http_method => :post,
39
+
40
+ :oauth_version => "1.0"
41
+ }
42
+
43
+ attr_accessor :options, :key, :secret
44
+ attr_writer :site, :http
45
+
46
+ # Create a new consumer instance by passing it a configuration hash:
47
+ #
48
+ # @consumer = OAuth::Consumer.new(key, secret, {
49
+ # :site => "http://term.ie",
50
+ # :scheme => :header,
51
+ # :http_method => :post,
52
+ # :request_token_path => "/oauth/example/request_token.php",
53
+ # :access_token_path => "/oauth/example/access_token.php",
54
+ # :authorize_path => "/oauth/example/authorize.php"
55
+ # })
56
+ #
57
+ # Start the process by requesting a token
58
+ #
59
+ # @request_token = @consumer.get_request_token
60
+ # session[:request_token] = @request_token
61
+ # redirect_to @request_token.authorize_url
62
+ #
63
+ # When user returns create an access_token
64
+ #
65
+ # @access_token = @request_token.get_access_token
66
+ # @photos=@access_token.get('/photos.xml')
67
+ #
68
+ def initialize(consumer_key, consumer_secret, options = {})
69
+ @key = consumer_key
70
+ @secret = consumer_secret
71
+
72
+ # ensure that keys are symbols
73
+ @options = @@default_options.merge(options.inject({}) { |options, (key, value)|
74
+ options[key.to_sym] = value
75
+ options
76
+ })
77
+ end
78
+
79
+ # The default http method
80
+ def http_method
81
+ @http_method ||= @options[:http_method] || :post
82
+ end
83
+
84
+ # The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
85
+ def http
86
+ @http ||= create_http
87
+ end
88
+
89
+ # Contains the root URI for this site
90
+ def uri(custom_uri = nil)
91
+ if custom_uri
92
+ @uri = custom_uri
93
+ @http = create_http # yike, oh well. less intrusive this way
94
+ else # if no custom passed, we use existing, which, if unset, is set to site uri
95
+ @uri ||= URI.parse(site)
96
+ end
97
+ end
98
+
99
+ # Makes a request to the service for a new OAuth::RequestToken
100
+ #
101
+ # @request_token = @consumer.get_request_token
102
+ #
103
+ def get_request_token(request_options = {}, *arguments)
104
+ response = token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
105
+ OAuth::RequestToken.new(self, response[:oauth_token], response[:oauth_token_secret])
106
+ end
107
+
108
+ # Creates, signs and performs an http request.
109
+ # It's recommended to use the OAuth::Token classes to set this up correctly.
110
+ # The arguments parameters are a hash or string encoded set of parameters if it's a post request as well as optional http headers.
111
+ #
112
+ # @consumer.request(:get, '/people', @token, { :scheme => :query_string })
113
+ # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
114
+ #
115
+ def request(http_method, path, token = nil, request_options = {}, *arguments)
116
+ if path !~ /^\//
117
+ @http = create_http(path)
118
+ _uri = URI.parse(path)
119
+ path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
120
+ end
121
+
122
+ rsp = http.request(create_signed_request(http_method, path, token, request_options, *arguments))
123
+
124
+ # check for an error reported by the Problem Reporting extension
125
+ # (http://wiki.oauth.net/ProblemReporting)
126
+ # note: a 200 may actually be an error; check for an oauth_problem key to be sure
127
+ if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
128
+ (h = headers.select { |h| h =~ /^OAuth / }).any? &&
129
+ h.first =~ /oauth_problem/
130
+
131
+ # puts "Header: #{h.first}"
132
+
133
+ # TODO doesn't handle broken responses from api.login.yahoo.com
134
+ # remove debug code when done
135
+ params = OAuth::Helper.parse_header(h.first)
136
+
137
+ # puts "Params: #{params.inspect}"
138
+ # puts "Body: #{rsp.body}"
139
+
140
+ raise OAuth::Problem.new(params.delete("oauth_problem"), rsp, params)
141
+ end
142
+
143
+ rsp
144
+ end
145
+
146
+ # Creates and signs an http request.
147
+ # It's recommended to use the Token classes to set this up correctly
148
+ def create_signed_request(http_method, path, token = nil, request_options = {}, *arguments)
149
+ request = create_http_request(http_method, path, *arguments)
150
+ sign!(request, token, request_options)
151
+ request
152
+ end
153
+
154
+ # Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
155
+ def token_request(http_method, path, token = nil, request_options = {}, *arguments)
156
+ response = request(http_method, path, token, request_options, *arguments)
157
+
158
+ case response.code.to_i
159
+
160
+ when (200..299)
161
+ CGI.parse(response.body).inject({}) { |h,(k,v)| h[k.to_sym] = v.first; h }
162
+ when (300..399)
163
+ # this is a redirect
164
+ response.error!
165
+ when (400..499)
166
+ raise OAuth::Unauthorized, response
167
+ else
168
+ response.error!
169
+ end
170
+ end
171
+
172
+ # Sign the Request object. Use this if you have an externally generated http request object you want to sign.
173
+ def sign!(request, token = nil, request_options = {})
174
+ request.oauth!(http, self, token, options.merge(request_options))
175
+ end
176
+
177
+ # Return the signature_base_string
178
+ def signature_base_string(request, token = nil, request_options = {})
179
+ request.signature_base_string(http, self, token, options.merge(request_options))
180
+ end
181
+
182
+ def site
183
+ @options[:site].to_s
184
+ end
185
+
186
+ def scheme
187
+ @options[:scheme]
188
+ end
189
+
190
+ def request_token_path
191
+ @options[:request_token_path]
192
+ end
193
+
194
+ def authorize_path
195
+ @options[:authorize_path]
196
+ end
197
+
198
+ def access_token_path
199
+ @options[:access_token_path]
200
+ end
201
+
202
+ # TODO this is ugly, rewrite
203
+ def request_token_url
204
+ @options[:request_token_url] || site + request_token_path
205
+ end
206
+
207
+ def request_token_url?
208
+ @options.has_key?(:request_token_url)
209
+ end
210
+
211
+ def authorize_url
212
+ @options[:authorize_url] || site + authorize_path
213
+ end
214
+
215
+ def authorize_url?
216
+ @options.has_key?(:authorize_url)
217
+ end
218
+
219
+ def access_token_url
220
+ @options[:access_token_url] || site + access_token_path
221
+ end
222
+
223
+ def access_token_url?
224
+ @options.has_key?(:access_token_url)
225
+ end
226
+
227
+ protected
228
+
229
+ # Instantiates the http object
230
+ def create_http(_url = nil)
231
+ if _url.nil? || _url[0] =~ /^\//
232
+ our_uri = URI.parse(site)
233
+ else
234
+ our_uri = URI.parse(_url)
235
+ end
236
+
237
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port)
238
+
239
+ http_object.use_ssl = (our_uri.scheme == 'https')
240
+
241
+ if CA_FILE
242
+ http_object.ca_file = CA_FILE
243
+ http_object.verify_mode = OpenSSL::SSL::VERIFY_PEER
244
+ http_object.verify_depth = 5
245
+ else
246
+ http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE
247
+ end
248
+
249
+ http_object
250
+ end
251
+
252
+ # create the http request object for a given http_method and path
253
+ def create_http_request(http_method, path, *arguments)
254
+ http_method = http_method.to_sym
255
+
256
+ if [:post, :put].include?(http_method)
257
+ data = arguments.shift
258
+ end
259
+
260
+ headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
261
+
262
+ case http_method
263
+ when :post
264
+ request = Net::HTTP::Post.new(path,headers)
265
+ request["Content-Length"] = 0 # Default to 0
266
+ when :put
267
+ request = Net::HTTP::Put.new(path,headers)
268
+ request["Content-Length"] = 0 # Default to 0
269
+ when :get
270
+ request = Net::HTTP::Get.new(path,headers)
271
+ when :delete
272
+ request = Net::HTTP::Delete.new(path,headers)
273
+ when :head
274
+ request = Net::HTTP::Head.new(path,headers)
275
+ else
276
+ raise ArgumentError, "Don't know how to handle http_method: :#{http_method.to_s}"
277
+ end
278
+
279
+ if data.is_a?(Hash)
280
+ request.set_form_data(data)
281
+ elsif data
282
+ request.body = data.to_s
283
+ request["Content-Length"] = request.body.length
284
+ end
285
+
286
+ request
287
+ end
288
+
289
+ # Unset cached http instance because it cannot be marshalled when
290
+ # it has already been used and use_ssl is set to true
291
+ def marshal_dump(*args)
292
+ @http = nil
293
+ self
294
+ end
295
+ end
296
+ end
@@ -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'
@@ -0,0 +1,55 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ module OAuth
5
+ module Helper
6
+ extend self
7
+
8
+ def escape(value)
9
+ URI::escape(value.to_s, OAuth::RESERVED_CHARACTERS)
10
+ end
11
+
12
+ def generate_key(size=32)
13
+ Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, '')
14
+ end
15
+
16
+ alias_method :generate_nonce, :generate_key
17
+
18
+ def generate_timestamp
19
+ Time.now.to_i.to_s
20
+ end
21
+
22
+ def normalize(params)
23
+ params.sort.map do |k, values|
24
+
25
+ if values.is_a?(Array)
26
+ # multiple values were provided for a single key
27
+ values.sort.collect do |v|
28
+ [escape(k),escape(v)] * "="
29
+ end
30
+ else
31
+ [escape(k),escape(values)] * "="
32
+ end
33
+ end * "&"
34
+ end
35
+
36
+ # Parse an Authorization / WWW-Authenticate header into a hash
37
+ def parse_header(header)
38
+ # decompose
39
+ params = header[6,header.length].split(/[,=]/)
40
+
41
+ # strip and unescape
42
+ params.map! { |v| unescape(v.strip) }
43
+
44
+ # strip quotes
45
+ params.map! { |v| v =~ /^\".*\"$/ ? v[1..-2] : v }
46
+
47
+ # convert into a Hash
48
+ Hash[*params.flatten]
49
+ end
50
+
51
+ def unescape(value)
52
+ URI.unescape(value.gsub('+', '%2B'))
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ module OAuth
2
+ # required parameters, per sections 6.1.1, 6.3.1, and 7
3
+ PARAMETERS = %w(oauth_consumer_key oauth_token oauth_signature_method oauth_timestamp oauth_nonce oauth_version oauth_signature)
4
+
5
+ # reserved character regexp, per section 5.1
6
+ RESERVED_CHARACTERS = /[^\w\d\-\.\_\~]/
7
+ end
@@ -0,0 +1,25 @@
1
+ require 'action_controller'
2
+ require 'action_controller/test_process'
3
+
4
+ module OAuth
5
+ module OAuthTestHelper
6
+ def mock_incoming_request_with_query(request)
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
+ incoming
13
+ end
14
+
15
+ def mock_incoming_request_with_authorize_header(request)
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
+ incoming
23
+ end
24
+ end
25
+ end