vincentchu-oauth 0.3.2.111

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/History.txt +70 -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.rb +4 -0
  10. data/lib/oauth/cli.rb +300 -0
  11. data/lib/oauth/client.rb +4 -0
  12. data/lib/oauth/client/action_controller_request.rb +53 -0
  13. data/lib/oauth/client/helper.rb +71 -0
  14. data/lib/oauth/client/net_http.rb +78 -0
  15. data/lib/oauth/consumer.rb +296 -0
  16. data/lib/oauth/errors.rb +3 -0
  17. data/lib/oauth/errors/error.rb +4 -0
  18. data/lib/oauth/errors/problem.rb +14 -0
  19. data/lib/oauth/errors/unauthorized.rb +12 -0
  20. data/lib/oauth/helper.rb +55 -0
  21. data/lib/oauth/oauth.rb +7 -0
  22. data/lib/oauth/oauth_test_helper.rb +25 -0
  23. data/lib/oauth/request_proxy.rb +24 -0
  24. data/lib/oauth/request_proxy/action_controller_request.rb +61 -0
  25. data/lib/oauth/request_proxy/base.rb +157 -0
  26. data/lib/oauth/request_proxy/jabber_request.rb +41 -0
  27. data/lib/oauth/request_proxy/mock_request.rb +44 -0
  28. data/lib/oauth/request_proxy/net_http.rb +65 -0
  29. data/lib/oauth/request_proxy/rack_request.rb +40 -0
  30. data/lib/oauth/server.rb +66 -0
  31. data/lib/oauth/signature.rb +28 -0
  32. data/lib/oauth/signature/base.rb +91 -0
  33. data/lib/oauth/signature/hmac/base.rb +12 -0
  34. data/lib/oauth/signature/hmac/md5.rb +9 -0
  35. data/lib/oauth/signature/hmac/rmd160.rb +9 -0
  36. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  37. data/lib/oauth/signature/hmac/sha2.rb +9 -0
  38. data/lib/oauth/signature/md5.rb +13 -0
  39. data/lib/oauth/signature/plaintext.rb +23 -0
  40. data/lib/oauth/signature/rsa/sha1.rb +45 -0
  41. data/lib/oauth/signature/sha1.rb +13 -0
  42. data/lib/oauth/token.rb +7 -0
  43. data/lib/oauth/tokens/access_token.rb +68 -0
  44. data/lib/oauth/tokens/consumer_token.rb +32 -0
  45. data/lib/oauth/tokens/request_token.rb +28 -0
  46. data/lib/oauth/tokens/server_token.rb +9 -0
  47. data/lib/oauth/tokens/token.rb +17 -0
  48. data/lib/oauth/version.rb +3 -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 +10 -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 +19 -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,4 @@
1
+ module OAuth
2
+ module Client
3
+ end
4
+ end
@@ -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,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