Class: Faraday::OAuth1::Request

Inherits:
Middleware
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/faraday/oauth1/request.rb

Overview

Public: Uses the simple_oauth library to sign requests according the OAuth 1 protocol.

The options for this middleware are forwarded to SimpleOAuth::Header: :consumer_key, :consumer_secret, :token, :token_secret. All these parameters are optional.

The signature is added to the “Authorization” HTTP request header. If the value for this header already exists, it is not overridden.

If no Content-Type header is specified, this middleware assumes that request body parameters should be included while signing the request. Otherwise, it only includes them if the Content-Type is “application/x-www-form-urlencoded”, as per OAuth 1.0.

For better performance while signing requests, this middleware should be positioned before UrlEncoded middleware on the stack, but after any other body-encoding middleware (such as EncodeJson).

Constant Summary collapse

AUTH_HEADER =
'Authorization'
CONTENT_TYPE =
'Content-Type'
TYPE_URLENCODED =
'application/x-www-form-urlencoded'
DEFAULT_AUTH_METHOD =
'param'
AUTH_METHODS =
[
  DEFAULT_AUTH_METHOD,
  'header'
].tap(&:freeze)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app = nil, auth_methods = nil, options = {}) ⇒ Request

Returns a new instance of Request.



44
45
46
47
48
49
# File 'lib/faraday/oauth1/request.rb', line 44

def initialize(app = nil, auth_methods = nil, options = {})
  super(app)
  @auth_methods = Array(auth_methods || DEFAULT_AUTH_METHOD)
  validate_auth_methods!
  @options = options
end

Instance Attribute Details

#auth_methodsObject (readonly)

Returns the value of attribute auth_methods.



42
43
44
# File 'lib/faraday/oauth1/request.rb', line 42

def auth_methods
  @auth_methods
end

Instance Method Details

#body_params(env) ⇒ Object



104
105
106
107
108
109
110
111
112
# File 'lib/faraday/oauth1/request.rb', line 104

def body_params(env)
  if include_body_params?(env)
    if env[:body].respond_to?(:to_str)
      parse_nested_query env[:body]
    else
      env[:body]
    end
  end || {}
end

#include_body_params?(env) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
117
# File 'lib/faraday/oauth1/request.rb', line 114

def include_body_params?(env)
  # see RFC 5849, section 3.4.1.3.1 for details
  !(type = env[:request_headers][CONTENT_TYPE]) || (type == TYPE_URLENCODED)
end

#oauth_header(env) ⇒ Object



84
85
86
87
88
89
# File 'lib/faraday/oauth1/request.rb', line 84

def oauth_header(env)
  SimpleOAuth::Header.new(env[:method],
                          env[:url].to_s,
                          signature_params(body_params(env)),
                          oauth_options(env))
end

#oauth_options(env) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/faraday/oauth1/request.rb', line 96

def oauth_options(env)
  if (extra = env[:request][:oauth]) && extra.is_a?(Hash) && !extra.empty?
    @options.merge extra
  else
    @options
  end
end

#on_request(env) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/faraday/oauth1/request.rb', line 51

def on_request(env)
  if sign_request?(env)
    header = oauth_header(env)
    auth_methods.each do |auth_method|
      case auth_method
      when 'param', :param
        params = {
          'oauth_consumer_key' => header.signed_attributes.fetch(:oauth_consumer_key),
          'oauth_signature_method' => header.signed_attributes.fetch(:oauth_signature_method),
          'oauth_timestamp' => header.signed_attributes.fetch(:oauth_timestamp),
          'oauth_nonce' => header.signed_attributes.fetch(:oauth_nonce),
          'oauth_version' => header.signed_attributes.fetch(:oauth_version),
          'oauth_signature' => header.signed_attributes.fetch(:oauth_signature)
        }
                 .merge(query_params(env[:url]))
        env[:url].query = build_query(params)
      when 'header', :header
        env[:request_headers][AUTH_HEADER] ||= header.to_s
      else
        raise ArgumentError, "invalid auth method: #{auth_method} not in #{AUTH_METHODS.join(', ')}"
      end
    end
  end
end

#query_params(url) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/faraday/oauth1/request.rb', line 127

def query_params(url)
  if url.query.nil? || url.query.empty?
    {}
  else
    parse_query url.query
  end
end

#sign_request?(env) ⇒ Boolean Also known as: process_request?

Returns:

  • (Boolean)


91
92
93
# File 'lib/faraday/oauth1/request.rb', line 91

def sign_request?(env)
  !!env[:request].fetch(:oauth, true)
end

#signature_params(params) ⇒ Object



119
120
121
122
123
124
125
# File 'lib/faraday/oauth1/request.rb', line 119

def signature_params(params)
  if params.empty?
    params
  else
    params.reject { |_k, v| v.respond_to?(:content_type) }
  end
end

#validate_auth_methods!Object

Raises:

  • (ArgumentError)


76
77
78
79
80
81
82
# File 'lib/faraday/oauth1/request.rb', line 76

def validate_auth_methods!
  invalid_auth_methods = auth_methods.map(&:to_s) - AUTH_METHODS
  return if invalid_auth_methods.empty?

  raise ArgumentError,
        "invalid auth method(s): #{invalid_auth_methods.join(', ')} not in #{AUTH_METHODS.join(', ')}"
end