Class: OAuth::Consumer

Inherits:
Object
  • Object
show all
Defined in:
lib/oauth/consumer.rb

Constant Summary collapse

CA_FILE =
nil
@@default_options =
SnakyHash::SymbolKeyed.new(
  {
    # Signature method used by server. Defaults to HMAC-SHA1
    signature_method: "HMAC-SHA1",
     # default paths on site. These are the same as the defaults set up by the generators
    request_token_path: "/oauth/request_token",
    authenticate_path: "/oauth/authenticate",
    authorize_path: "/oauth/authorize",
    access_token_path: "/oauth/access_token",
     proxy: nil,
    # How do we send the oauth values to the server see
    # https://oauth.net/core/1.0/#consumer_req_param for more info
    #
    # Possible values:
    #
    #   :header - via the Authorize header (Default) ( option 1. in spec)
    #   :body - url form encoded in body of POST request ( option 2. in spec)
    #   :query_string - via the query part of the url ( option 3. in spec)
    scheme: :header,
     # Default http method used for OAuth Token Requests (defaults to :post)
    http_method: :post,
     # Add a custom ca_file for consumer
    # :ca_file       => '/etc/certs.pem'
     # Possible values:
    #
    # nil, false - no debug output
    # true - uses $stdout
    # some_value - uses some_value
    debug_output: nil,
     # Defaults to producing a body_hash as part of the signature but
    # can be disabled since it's not officially part of the OAuth 1.0
    # spec. Possible values are true and false
    body_hash_enabled: true,
     oauth_version: "1.0"
  }
)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(consumer_key, consumer_secret, options = {}) ⇒ Consumer

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')


103
104
105
106
107
108
109
110
# File 'lib/oauth/consumer.rb', line 103

def initialize(consumer_key, consumer_secret, options = {})
  @key    = consumer_key
  @secret = consumer_secret

  # ensure that keys are symbols
  snaky_options = SnakyHash::SymbolKeyed.new(options)
  @options = @@default_options.merge(snaky_options)
end

Instance Attribute Details

#httpObject

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



128
129
130
# File 'lib/oauth/consumer.rb', line 128

def http
  @http ||= create_http
end

#keyObject

Returns the value of attribute key.



77
78
79
# File 'lib/oauth/consumer.rb', line 77

def key
  @key
end

#optionsObject

Returns the value of attribute options.



77
78
79
# File 'lib/oauth/consumer.rb', line 77

def options
  @options
end

#secretObject

Returns the value of attribute secret.



77
78
79
# File 'lib/oauth/consumer.rb', line 77

def secret
  @secret
end

#siteObject



286
287
288
# File 'lib/oauth/consumer.rb', line 286

def site
  @options[:site].to_s
end

Instance Method Details

#access_token_pathObject



312
313
314
# File 'lib/oauth/consumer.rb', line 312

def access_token_path
  @options[:access_token_path]
end

#access_token_urlObject



341
342
343
# File 'lib/oauth/consumer.rb', line 341

def access_token_url
  @options[:access_token_url] || (site + access_token_path)
end

#access_token_url?Boolean

Returns:

  • (Boolean)


345
346
347
# File 'lib/oauth/consumer.rb', line 345

def access_token_url?
  @options.key?(:access_token_url)
end

#authenticate_pathObject



304
305
306
# File 'lib/oauth/consumer.rb', line 304

def authenticate_path
  @options[:authenticate_path]
end

#authenticate_urlObject



325
326
327
# File 'lib/oauth/consumer.rb', line 325

def authenticate_url
  @options[:authenticate_url] || (site + authenticate_path)
end

#authenticate_url?Boolean

Returns:

  • (Boolean)


329
330
331
# File 'lib/oauth/consumer.rb', line 329

def authenticate_url?
  @options.key?(:authenticate_url)
end

#authorize_pathObject



308
309
310
# File 'lib/oauth/consumer.rb', line 308

def authorize_path
  @options[:authorize_path]
end

#authorize_urlObject



333
334
335
# File 'lib/oauth/consumer.rb', line 333

def authorize_url
  @options[:authorize_url] || (site + authorize_path)
end

#authorize_url?Boolean

Returns:

  • (Boolean)


337
338
339
# File 'lib/oauth/consumer.rb', line 337

def authorize_url?
  @options.key?(:authorize_url)
end

#create_signed_request(http_method, path, token = nil, request_options = {}, *arguments) ⇒ Object

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



231
232
233
234
235
# File 'lib/oauth/consumer.rb', line 231

def create_signed_request(http_method, path, token = nil, request_options = {}, *arguments)
  request = create_http_request(http_method, path, *arguments)
  sign!(request, token, request_options)
  request
end

#debug_outputObject



117
118
119
120
121
122
123
124
125
# File 'lib/oauth/consumer.rb', line 117

def debug_output
  @debug_output ||= case @options[:debug_output]
                    when nil, false
                    when true
                      $stdout
                    else
                      @options[:debug_output]
                    end
end

#get_access_token(request_token, request_options = {}, *arguments, &block) ⇒ Object



142
143
144
145
146
# File 'lib/oauth/consumer.rb', line 142

def get_access_token(request_token, request_options = {}, *arguments, &block)
  response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token,
                           request_options, *arguments, &block)
  OAuth::AccessToken.from_hash(self, response)
end

#get_request_token(request_options = {}, *arguments, &block) ⇒ Object

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

@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")

TODO oauth_callback should be a mandatory parameter



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/oauth/consumer.rb', line 162

def get_request_token(request_options = {}, *arguments, &block)
  # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
  # will be exchanged out of band
  unless request_options[:exclude_callback]
    request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND
  end

  response = if block
               token_request(
                 http_method,
                 (request_token_url? ? request_token_url : request_token_path),
                 nil,
                 request_options,
                 *arguments,
                 &block
               )
             else
               token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil,
                             request_options, *arguments)
             end
  OAuth::RequestToken.from_hash(self, response)
end

#http_methodObject

The default http method



113
114
115
# File 'lib/oauth/consumer.rb', line 113

def http_method
  @http_method ||= @options[:http_method] || :post
end

#proxyObject



349
350
351
# File 'lib/oauth/consumer.rb', line 349

def proxy
  @options[:proxy]
end

#request(http_method, path, token = nil, request_options = {}, *arguments) ⇒ Object

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' })


195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/oauth/consumer.rb', line 195

def request(http_method, path, token = nil, request_options = {}, *arguments)
  unless %r{^/}.match?(path)
    @http = create_http(path)
    _uri = URI.parse(path)
    path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
  end

  # override the request with your own, this is useful for file uploads which Net::HTTP does not do
  req = create_signed_request(http_method, path, token, request_options, *arguments)
  return nil if block_given? && (yield(req) == :done)

  rsp = http.request(req)
  # check for an error reported by the Problem Reporting extension
  # (https://wiki.oauth.net/ProblemReporting)
  # note: a 200 may actually be an error; check for an oauth_problem key to be sure
  if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
     (h = headers.grep(/^OAuth /)).any? &&
     h.first.include?("oauth_problem")

    # puts "Header: #{h.first}"

    # TODO: doesn't handle broken responses from api.login.yahoo.com
    # remove debug code when done
    params = OAuth::Helper.parse_header(h.first)

    # puts "Params: #{params.inspect}"
    # puts "Body: #{rsp.body}"

    raise OAuth::Problem.new(params.delete("oauth_problem"), rsp, params)
  end

  rsp
end

#request_endpointObject



290
291
292
293
294
# File 'lib/oauth/consumer.rb', line 290

def request_endpoint
  return nil if @options[:request_endpoint].nil?

  @options[:request_endpoint].to_s
end

#request_token_pathObject



300
301
302
# File 'lib/oauth/consumer.rb', line 300

def request_token_path
  @options[:request_token_path]
end

#request_token_urlObject

TODO: this is ugly, rewrite



317
318
319
# File 'lib/oauth/consumer.rb', line 317

def request_token_url
  @options[:request_token_url] || (site + request_token_path)
end

#request_token_url?Boolean

Returns:

  • (Boolean)


321
322
323
# File 'lib/oauth/consumer.rb', line 321

def request_token_url?
  @options.key?(:request_token_url)
end

#schemeObject



296
297
298
# File 'lib/oauth/consumer.rb', line 296

def scheme
  @options[:scheme]
end

#sign!(request, token = nil, request_options = {}) ⇒ Object

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



277
278
279
# File 'lib/oauth/consumer.rb', line 277

def sign!(request, token = nil, request_options = {})
  request.oauth!(http, self, token, options.merge(request_options))
end

#signature_base_string(request, token = nil, request_options = {}) ⇒ Object

Return the signature_base_string



282
283
284
# File 'lib/oauth/consumer.rb', line 282

def signature_base_string(request, token = nil, request_options = {})
  request.signature_base_string(http, self, token, options.merge(request_options))
end

#token_request(http_method, path, token = nil, request_options = {}, *arguments) ⇒ Object

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



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/oauth/consumer.rb', line 238

def token_request(http_method, path, token = nil, request_options = {}, *arguments)
  request_options[:token_request] ||= true
  response = request(http_method, path, token, request_options, *arguments)
  case response.code.to_i

  when (200..299)
    if block_given?
      yield response.body
    else
      # symbolize keys
      # TODO this could be considered unexpected behavior; symbols or not?
      # TODO this also drops subsequent values from multi-valued keys
      CGI.parse(response.body).each_with_object({}) do |(k, v), h|
        h[k.strip.to_sym] = v.first
        h[k.strip]        = v.first
      end
    end
  when (300..399)
    # Parse redirect to follow
    uri = URI.parse(response["location"])
    our_uri = URI.parse(site)

    # Guard against infinite redirects
    response.error! if uri.path == path && our_uri.host == uri.host

    if uri.path == path && our_uri.host != uri.host
      options[:site] = "#{uri.scheme}://#{uri.host}"
      @http = create_http
    end

    token_request(http_method, uri.path, token, request_options, arguments)
  when (400..499)
    raise OAuth::Unauthorized, response
  else
    response.error!
  end
end

#uri(custom_uri = nil) ⇒ Object

Contains the root URI for this site



133
134
135
136
137
138
139
140
# File 'lib/oauth/consumer.rb', line 133

def uri(custom_uri = nil)
  if custom_uri
    @uri  = custom_uri
    @http = create_http # yike, oh well. less intrusive this way
  else # if no custom passed, we use existing, which, if unset, is set to site uri
    @uri ||= URI.parse(site)
  end
end