class OAuth::Consumer

Constants

CA_FILE
CA_FILES

Attributes

http[W]
key[RW]
options[RW]
secret[RW]
site[W]

Public Class Methods

new(consumer_key, consumer_secret, options = {}) click to toggle source

Create a new consumer instance by passing it a configuration hash:

@consumer = OAuth::Consumer.new(key, secret, {
  :site               => "http://term.ie",
  :scheme             => :header,
  :http_method        => :post,
  :request_token_path => "/oauth/example/request_token.php",
  :access_token_path  => "/oauth/example/access_token.php",
  :authorize_path     => "/oauth/example/authorize.php",
  :body_hash_enabled  => false
 })

Start the process by requesting a token

@request_token = @consumer.get_request_token
session[:request_token] = @request_token
redirect_to @request_token.authorize_url

When user returns create an access_token

@access_token = @request_token.get_access_token
@photos=@access_token.get('/photos.xml')
    # File lib/oauth/consumer.rb
106 def initialize(consumer_key, consumer_secret, options = {})
107   @key = consumer_key
108   @secret = consumer_secret
109 
110   # ensure that keys are symbols
111   snaky_options = SnakyHash::SymbolKeyed.new(options)
112   @options = @@default_options.merge(snaky_options)
113 end

Public Instance Methods

access_token_path() click to toggle source
    # File lib/oauth/consumer.rb
355 def access_token_path
356   @options[:access_token_path]
357 end
access_token_url() click to toggle source
    # File lib/oauth/consumer.rb
384 def access_token_url
385   @options[:access_token_url] || (site + access_token_path)
386 end
access_token_url?() click to toggle source
    # File lib/oauth/consumer.rb
388 def access_token_url?
389   @options.key?(:access_token_url)
390 end
authenticate_path() click to toggle source
    # File lib/oauth/consumer.rb
347 def authenticate_path
348   @options[:authenticate_path]
349 end
authenticate_url() click to toggle source
    # File lib/oauth/consumer.rb
368 def authenticate_url
369   @options[:authenticate_url] || (site + authenticate_path)
370 end
authenticate_url?() click to toggle source
    # File lib/oauth/consumer.rb
372 def authenticate_url?
373   @options.key?(:authenticate_url)
374 end
authorize_path() click to toggle source
    # File lib/oauth/consumer.rb
351 def authorize_path
352   @options[:authorize_path]
353 end
authorize_url() click to toggle source
    # File lib/oauth/consumer.rb
376 def authorize_url
377   @options[:authorize_url] || (site + authorize_path)
378 end
authorize_url?() click to toggle source
    # File lib/oauth/consumer.rb
380 def authorize_url?
381   @options.key?(:authorize_url)
382 end
create_signed_request(http_method, path, token = nil, request_options = {}, *arguments) click to toggle source

Creates and signs an http request. It's recommended to use the Token classes to set this up correctly

    # File lib/oauth/consumer.rb
274 def create_signed_request(http_method, path, token = nil, request_options = {}, *arguments)
275   request = create_http_request(http_method, path, *arguments)
276   sign!(request, token, request_options)
277   request
278 end
debug_output() click to toggle source
    # File lib/oauth/consumer.rb
120 def debug_output
121   @debug_output ||= case @options[:debug_output]
122   when nil, false
123   when true
124     $stdout
125   else
126     @options[:debug_output]
127   end
128 end
get_access_token(request_token, request_options = {}, *arguments, &block) click to toggle source

Exchanges a verified Request Token for an Access Token.

OAuth 1.0 vs 1.0a:

  • 1.0a requires including oauth_verifier (as returned by the Provider after user authorization) when performing this exchange in a 3‑legged flow.

  • 1.0 flows did not include oauth_verifier.

Usage (3‑legged):

access_token = request_token.get_access_token(oauth_verifier: params[:oauth_verifier])

@param request_token [OAuth::RequestToken] The authorized request token @param request_options [Hash] OAuth or request options (include :oauth_verifier for 1.0a) @param arguments [Array] Optional POST body and headers @yield [response_body] If a block is given, yields the raw response body. @return [OAuth::AccessToken]

    # File lib/oauth/consumer.rb
160 def get_access_token(request_token, request_options = {}, *arguments, &block)
161   response = token_request(
162     http_method,
163     (access_token_url? ? access_token_url : access_token_path),
164     request_token,
165     request_options,
166     *arguments,
167     &block
168   )
169   OAuth::AccessToken.from_hash(self, response)
170 end
get_request_token(request_options = {}, *arguments, &block) click to toggle source

Makes a request to the service for a new OAuth::RequestToken

Example:

@request_token = @consumer.get_request_token

To include OAuth parameters:

@request_token = @consumer.get_request_token(
  oauth_callback: "http://example.com/cb"
)

To include application-specific parameters:

@request_token = @consumer.get_request_token({}, foo: "bar")

OAuth 1.0 vs 1.0a:

  • In 1.0a, the Consumer SHOULD send oauth_callback when obtaining a request token (or explicitly use OUT_OF_BAND) and the Provider MUST include oauth_callback_confirmed=true in the response.

  • This library defaults oauth_callback to OUT_OF_BAND (“oob”) when not provided, which works for both 1.0 and 1.0a, and mirrors common provider behavior.

  • The oauth_callback_confirmed response is parsed by the token classes; it is not part of the signature base string and thus is not signed.

TODO: In a future major release, oauth_callback may be made mandatory unless

request_options[:exclude_callback] is set, to reflect 1.0a guidance.

@param request_options [Hash] OAuth options for the request. Notably

:oauth_callback can be set to a URL, or OAuth::OUT_OF_BAND ("oob").

@param arguments [Array] Optional POST body and headers @yield [response_body] If a block is given, yields the raw response body. @return [OAuth::RequestToken]

    # File lib/oauth/consumer.rb
202 def get_request_token(request_options = {}, *arguments, &block)
203   # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
204   # will be exchanged out of band
205   request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
206 
207   response = if block
208     token_request(
209       http_method,
210       (request_token_url? ? request_token_url : request_token_path),
211       nil,
212       request_options,
213       *arguments,
214       &block
215     )
216   else
217     token_request(
218       http_method,
219       (request_token_url? ? request_token_url : request_token_path),
220       nil,
221       request_options,
222       *arguments,
223     )
224   end
225   OAuth::RequestToken.from_hash(self, response)
226 end
http() click to toggle source

The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new

    # File lib/oauth/consumer.rb
131 def http
132   @http ||= create_http
133 end
http_method() click to toggle source

The default http method

    # File lib/oauth/consumer.rb
116 def http_method
117   @http_method ||= @options[:http_method] || :post
118 end
proxy() click to toggle source
    # File lib/oauth/consumer.rb
392 def proxy
393   @options[:proxy]
394 end
request(http_method, path, token = nil, request_options = {}, *arguments) { |req| ... } click to toggle source

Creates, signs and performs an http request. It's recommended to use the OAuth::Token classes to set this up correctly. request_options take precedence over consumer-wide options when signing

a request.

arguments are POST and PUT bodies (a Hash, string-encoded parameters, or

absent), followed by additional HTTP headers.

@consumer.request(:get,  '/people', @token, { :scheme => :query_string })
@consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
    # File lib/oauth/consumer.rb
238 def request(http_method, path, token = nil, request_options = {}, *arguments)
239   unless %r{^/} =~ path
240     @http = create_http(path)
241     _uri = URI.parse(path)
242     path = "#{_uri.path}#{"?#{_uri.query}" if _uri.query}"
243   end
244 
245   # override the request with your own, this is useful for file uploads which Net::HTTP does not do
246   req = create_signed_request(http_method, path, token, request_options, *arguments)
247   return if block_given? && (yield(req) == :done)
248 
249   rsp = http.request(req)
250   # check for an error reported by the Problem Reporting extension
251   # (https://wiki.oauth.net/ProblemReporting)
252   # note: a 200 may actually be an error; check for an oauth_problem key to be sure
253   if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
254       (h = headers.grep(/^OAuth /)).any? &&
255       h.first.include?("oauth_problem")
256 
257     # puts "Header: #{h.first}"
258 
259     # TODO: doesn't handle broken responses from api.login.yahoo.com
260     # remove debug code when done
261     params = OAuth::Helper.parse_header(h.first)
262 
263     # puts "Params: #{params.inspect}"
264     # puts "Body: #{rsp.body}"
265 
266     raise OAuth::Problem.new(params.delete("oauth_problem"), rsp, params)
267   end
268 
269   rsp
270 end
request_endpoint() click to toggle source
    # File lib/oauth/consumer.rb
333 def request_endpoint
334   return if @options[:request_endpoint].nil?
335 
336   @options[:request_endpoint].to_s
337 end
request_token_path() click to toggle source
    # File lib/oauth/consumer.rb
343 def request_token_path
344   @options[:request_token_path]
345 end
request_token_url() click to toggle source

TODO: this is ugly, rewrite

    # File lib/oauth/consumer.rb
360 def request_token_url
361   @options[:request_token_url] || (site + request_token_path)
362 end
request_token_url?() click to toggle source
    # File lib/oauth/consumer.rb
364 def request_token_url?
365   @options.key?(:request_token_url)
366 end
scheme() click to toggle source
    # File lib/oauth/consumer.rb
339 def scheme
340   @options[:scheme]
341 end
sign!(request, token = nil, request_options = {}) click to toggle source

Sign the Request object. Use this if you have an externally generated http request object you want to sign.

    # File lib/oauth/consumer.rb
320 def sign!(request, token = nil, request_options = {})
321   request.oauth!(http, self, token, options.merge(request_options))
322 end
signature_base_string(request, token = nil, request_options = {}) click to toggle source

Return the signature_base_string

    # File lib/oauth/consumer.rb
325 def signature_base_string(request, token = nil, request_options = {})
326   request.signature_base_string(http, self, token, options.merge(request_options))
327 end
site() click to toggle source
    # File lib/oauth/consumer.rb
329 def site
330   @options[:site].to_s
331 end
token_request(http_method, path, token = nil, request_options = {}, *arguments) { |body| ... } click to toggle source

Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.

    # File lib/oauth/consumer.rb
281 def token_request(http_method, path, token = nil, request_options = {}, *arguments)
282   request_options[:token_request] ||= true
283   response = request(http_method, path, token, request_options, *arguments)
284   case response.code.to_i
285 
286   when (200..299)
287     if block_given?
288       yield response.body
289     else
290       # symbolize keys
291       # TODO this could be considered unexpected behavior; symbols or not?
292       # TODO this also drops subsequent values from multi-valued keys
293       CGI.parse(response.body).each_with_object({}) do |(k, v), h|
294         h[k.strip.to_sym] = v.first
295         h[k.strip] = v.first
296       end
297     end
298   when (300..399)
299     # Parse redirect to follow
300     uri = URI.parse(response["location"])
301     our_uri = URI.parse(site)
302 
303     # Guard against infinite redirects
304     response.error! if uri.path == path && our_uri.host == uri.host
305 
306     if uri.path == path && our_uri.host != uri.host
307       options[:site] = "#{uri.scheme}://#{uri.host}"
308       @http = create_http
309     end
310 
311     token_request(http_method, uri.path, token, request_options, arguments)
312   when (400..499)
313     raise OAuth::Unauthorized, response
314   else
315     response.error!
316   end
317 end
uri(custom_uri = nil) click to toggle source

Contains the root URI for this site

    # File lib/oauth/consumer.rb
136 def uri(custom_uri = nil)
137   if custom_uri
138     @uri = custom_uri
139     @http = create_http # yike, oh well. less intrusive this way
140   else # if no custom passed, we use existing, which, if unset, is set to site uri
141     @uri ||= URI.parse(site)
142   end
143 end

Protected Instance Methods

create_http(_url = nil) click to toggle source

Instantiates the http object

    # File lib/oauth/consumer.rb
399 def create_http(_url = nil)
400   _url = request_endpoint unless request_endpoint.nil?
401 
402   our_uri = if _url.nil? || _url[0] =~ %r{^/}
403     URI.parse(site)
404   else
405     your_uri = URI.parse(_url)
406     if your_uri.host.nil?
407       # If the _url is a path, missing the leading slash, then it won't have a host,
408       # and our_uri *must* have a host, so we parse site instead.
409       URI.parse(site)
410     else
411       your_uri
412     end
413   end
414 
415   if proxy.nil?
416     http_object = Net::HTTP.new(our_uri.host, our_uri.port)
417   else
418     proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
419     http_object = Net::HTTP.new(
420       our_uri.host,
421       our_uri.port,
422       proxy_uri.host,
423       proxy_uri.port,
424       proxy_uri.user,
425       proxy_uri.password,
426     )
427   end
428 
429   http_object.use_ssl = (our_uri.scheme == "https")
430 
431   if @options[:no_verify]
432     http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE
433   else
434     ca_file = @options[:ca_file] || CA_FILE
435     http_object.ca_file = ca_file if ca_file
436     http_object.verify_mode = OpenSSL::SSL::VERIFY_PEER
437     http_object.verify_depth = 5
438   end
439 
440   http_object.read_timeout = http_object.open_timeout = @options[:timeout] || 60
441   http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
442   http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
443   http_object.cert = @options[:ssl_client_cert] if @options[:ssl_client_cert]
444   http_object.key = @options[:ssl_client_key] if @options[:ssl_client_key]
445   http_object.set_debug_output(debug_output) if debug_output
446 
447   http_object
448 end
create_http_request(http_method, path, *arguments) click to toggle source

create the http request object for a given http_method and path

    # File lib/oauth/consumer.rb
451 def create_http_request(http_method, path, *arguments)
452   http_method = http_method.to_sym
453 
454   data = arguments.shift if %i[post put patch].include?(http_method)
455 
456   # if the base site contains a path, add it now
457   # only add if the site host matches the current http object's host
458   # (in case we've specified a full url for token requests)
459   uri = URI.parse(site)
460   path = uri.path + path if uri.path && uri.path != "/" && uri.host == http.address
461 
462   headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
463 
464   case http_method
465   when :post
466     request = Net::HTTP::Post.new(path, headers)
467     request["Content-Length"] = "0" # Default to 0
468   when :put
469     request = Net::HTTP::Put.new(path, headers)
470     request["Content-Length"] = "0" # Default to 0
471   when :patch
472     request = Net::HTTP::Patch.new(path, headers)
473     request["Content-Length"] = "0" # Default to 0
474   when :get
475     request = Net::HTTP::Get.new(path, headers)
476   when :delete
477     request = Net::HTTP::Delete.new(path, headers)
478   when :head
479     request = Net::HTTP::Head.new(path, headers)
480   else
481     raise ArgumentError, "Don't know how to handle http_method: :#{http_method}"
482   end
483 
484   if data.is_a?(Hash)
485     request.body = OAuth::Helper.normalize(data)
486     request.content_type = "application/x-www-form-urlencoded"
487   elsif data
488     if data.respond_to?(:read)
489       request.body_stream = data
490       if data.respond_to?(:length)
491         request["Content-Length"] = data.length.to_s
492       elsif data.respond_to?(:stat) && data.stat.respond_to?(:size)
493         request["Content-Length"] = data.stat.size.to_s
494       else
495         raise ArgumentError, "Don't know how to send a body_stream that doesn't respond to .length or .stat.size"
496       end
497     else
498       request.body = data.to_s
499       request["Content-Length"] = request.body.length.to_s
500     end
501   end
502 
503   request
504 end
marshal_dump(*_args) click to toggle source
    # File lib/oauth/consumer.rb
506 def marshal_dump(*_args)
507   {key: @key, secret: @secret, options: @options}
508 end
marshal_load(data) click to toggle source
    # File lib/oauth/consumer.rb
510 def marshal_load(data)
511   initialize(data[:key], data[:secret], data[:options])
512 end