Class: OAuth::Consumer

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

Constant Summary collapse

CA_FILE =
nil
CA_FILES =
%W(/etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt /usr/share/curl/curl-ca-bundle.crt)
@@default_options =
{
  # 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
  # http://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,
   :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"
 })

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


92
93
94
95
96
97
98
99
100
101
# File 'lib/oauth/consumer.rb', line 92

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

  # ensure that keys are symbols
  @options = @@default_options.merge(options.inject({}) do |opts, (key, value)|
    opts[key.to_sym] = value
    opts
  end)
end

Instance Attribute Details

#httpObject

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



121
122
123
# File 'lib/oauth/consumer.rb', line 121

def http
  @http ||= create_http
end

#keyObject

Returns the value of attribute key.



67
68
69
# File 'lib/oauth/consumer.rb', line 67

def key
  @key
end

#optionsObject

Returns the value of attribute options.



67
68
69
# File 'lib/oauth/consumer.rb', line 67

def options
  @options
end

#secretObject

Returns the value of attribute secret.



67
68
69
# File 'lib/oauth/consumer.rb', line 67

def secret
  @secret
end

#siteObject



270
271
272
# File 'lib/oauth/consumer.rb', line 270

def site
  @options[:site].to_s
end

Instance Method Details

#access_token_pathObject



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

def access_token_path
  @options[:access_token_path]
end

#access_token_urlObject



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

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

#access_token_url?Boolean

Returns:

  • (Boolean)


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

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

#authenticate_pathObject



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

def authenticate_path
  @options[:authenticate_path]
end

#authenticate_urlObject



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

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

#authenticate_url?Boolean

Returns:

  • (Boolean)


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

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

#authorize_pathObject



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

def authorize_path
  @options[:authorize_path]
end

#authorize_urlObject



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

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

#authorize_url?Boolean

Returns:

  • (Boolean)


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

def authorize_url?
  @options.has_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



216
217
218
219
220
# File 'lib/oauth/consumer.rb', line 216

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



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/oauth/consumer.rb', line 108

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

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



135
136
137
138
# File 'lib/oauth/consumer.rb', line 135

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



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/oauth/consumer.rb', line 154

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
  request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]

  if block_given?
    response = token_request(http_method,
    (request_token_url? ? request_token_url : request_token_path),
    nil,
    request_options,
    *arguments, &block)
  else
    response = 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



104
105
106
# File 'lib/oauth/consumer.rb', line 104

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

#proxyObject



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

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


181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/oauth/consumer.rb', line 181

def request(http_method, path, token = nil, request_options = {}, *arguments)
  if 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? and yield(req) == :done
  rsp = http.request(req)
  # check for an error reported by the Problem Reporting extension
  # (http://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.select { |hdr| hdr =~ /^OAuth / }).any? &&
    h.first =~ /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



274
275
276
277
# File 'lib/oauth/consumer.rb', line 274

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

#request_token_pathObject



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

def request_token_path
  @options[:request_token_path]
end

#request_token_urlObject

TODO this is ugly, rewrite



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

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

#request_token_url?Boolean

Returns:

  • (Boolean)


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

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

#schemeObject



279
280
281
# File 'lib/oauth/consumer.rb', line 279

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.



261
262
263
# File 'lib/oauth/consumer.rb', line 261

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



266
267
268
# File 'lib/oauth/consumer.rb', line 266

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.



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/oauth/consumer.rb', line 223

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).inject({}) do |h,(k,v)|
        h[k.strip.to_sym] = v.first
        h[k.strip]        = v.first
        h
      end
    end
  when (300..399)
    # this is a redirect
    uri = URI.parse(response['location'])
    our_uri = URI.parse(site)

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

    response.error! if uri.path == path && our_uri.host == uri.host # careful of those infinite redirects
    self.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



126
127
128
129
130
131
132
133
# File 'lib/oauth/consumer.rb', line 126

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