Method: OAuthenticator::SignableRequest#initialize

Defined in:
lib/oauthenticator/signable_request.rb

#initialize(attributes) ⇒ SignableRequest

initialize a signable request with the following attributes (keys may be string or symbol):

  • request_method (required) - get, post, etc. may be string or symbol.
  • uri (required) - request URI. to_s is called so URI or Addressable::URI or whatever may be passed.
  • media_type (required) - the request media type (may be nil if there is no body). note that this may be different than the Content-Type header; other components of that such as encoding must not be included.
  • body (required) - the request body. may be a String or an IO, or nil if no body is present.
  • hash_body? - whether to add the oauth_body_hash parameter, per the OAuth Request Body Hash specification. defaults to true. not used if the 'authorization' parameter is used.
  • signature_method (required*) - oauth signature method (String)
  • consumer_key (required*) - oauth consumer key (String)
  • consumer_secret (required*) - oauth consumer secret (String)
  • token (optional*) - oauth token; may be omitted if only using a consumer key (two-legged)
  • token_secret (optional) - must be present if token is present. must be omitted if token is omitted.
  • timestamp (optional*) - if omitted, defaults to the current time. if nil is passed, no oauth_timestamp will be present in the generated authorization.
  • nonce (optional*) - if omitted, defaults to a random string. if nil is passed, no oauth_nonce will be present in the generated authorization.
  • version (optional*) - must be nil or '1.0'. defaults to '1.0' if omitted. if nil is passed, no oauth_version will be present in the generated authorization.
  • realm (optional) - authorization realm. if nil is passed, no realm will be present in the generated authorization.
  • authorization - a hash of a received Authorization header, the result of a call to OAuthenticator.parse_authorization. it is useful for calculating the signature of a received request, but for fully authenticating a received request it is generally preferable to use OAuthenticator::SignedRequest. specifying this precludes the requirement to specify any of PROTOCOL_PARAM_KEYS.

(*) attributes which are in PROTOCOL_PARAM_KEYS are unused (and not required) when the 'authorization' attribute is given for signature verification. normally, though, they are used and are required or optional as noted.

Raises:

  • (TypeError)


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/oauthenticator/signable_request.rb', line 63

def initialize(attributes)
  raise TypeError, "attributes must be a hash" unless attributes.is_a?(Hash)
  # stringify symbol keys
  @attributes = attributes.map { |k,v| {k.is_a?(Symbol) ? k.to_s : k => v} }.inject({}, &:update)

  # validation - presence
  required = %w(request_method uri media_type body)
  required += %w(signature_method consumer_key) unless @attributes['authorization']
  missing = required - @attributes.keys
  raise ArgumentError, "missing required attributes: #{missing.inspect}" if missing.any?
  other_recognized = PROTOCOL_PARAM_KEYS + %w(authorization consumer_secret token_secret realm hash_body?)
  extra = @attributes.keys - (required + other_recognized)
  raise ArgumentError, "received unrecognized attributes: #{extra.inspect}" if extra.any?

  if @attributes['authorization']
    # this means we are signing an existing request to validate the received signature. don't use defaults.
    unless @attributes['authorization'].is_a?(Hash)
      raise TypeError, "authorization must be a Hash"
    end

    # if authorization is specified, protocol params should not be specified in the regular attributes 
    given_protocol_params = @attributes.reject { |k,v| !(PROTOCOL_PARAM_KEYS.include?(k) && v) }
    if given_protocol_params.any?
      raise ArgumentError, "an existing authorization was given, but protocol parameters were also " +
        "given. protocol parameters should not be specified when verifying an existing authorization. " +
        "given protocol parameters were: #{given_protocol_params.inspect}"
    end
  else
    # defaults
    defaults = {
      'version' => '1.0',
    }
    if @attributes['signature_method'] != 'PLAINTEXT'
      defaults.update({
        'nonce' => OpenSSL::Random.random_bytes(16).unpack('H*')[0],
        'timestamp' => Time.now.to_i.to_s,
      })
    end
    @attributes['authorization'] = PROTOCOL_PARAM_KEYS.map do |key|
      {"oauth_#{key}" => @attributes.key?(key) ? @attributes[key] : defaults[key]}
    end.inject({}, &:update).reject {|k,v| v.nil? }
    @attributes['authorization']['realm'] = @attributes['realm'] unless @attributes['realm'].nil?

    hash_body
  end
end