Class: SimpleOAuth::Header

Inherits:
Object
  • Object
show all
Extended by:
Encoding, ClassMethods
Includes:
Params
Defined in:
lib/simple_oauth/header.rb,
lib/simple_oauth/header/params.rb,
lib/simple_oauth/header/class_methods.rb,
sig/simple_oauth.rbs,
sig/simple_oauth/header/params.rbs,
sig/simple_oauth/header/class_methods.rbs

Overview

Generates OAuth 1.0 Authorization headers for HTTP requests

Defined Under Namespace

Modules: ClassMethods, Params, _HeaderFactory, _Request, _Signable

Constant Summary collapse

OAUTH_SCHEME =

OAuth header scheme prefix

Returns:

  • (String)
"OAuth"
OAUTH_PREFIX =

Prefix for OAuth parameters

Returns:

  • (String)
"oauth_"
FORM_CONTENT_TYPE =

The content type whose body parameters are signed

Returns:

  • (String)
"application/x-www-form-urlencoded"
DEFAULT_SIGNATURE_METHOD =

Default signature method per RFC 5849

Returns:

  • (String)
"HMAC-SHA1"
OAUTH_VERSION =

OAuth version

Returns:

  • (String)
"1.0"
ATTRIBUTE_KEYS =

Valid OAuth attribute keys that can be included in the header

Returns:

  • (Array[Symbol])
%i[body_hash callback consumer_key nonce signature_method timestamp token verifier version].freeze
IGNORED_KEYS =

Keys that are used internally but should not appear in attributes

Returns:

  • (Array[Symbol])
%i[consumer_secret token_secret signature realm ignore_extra_keys].freeze
PARSE_KEYS =

Valid keys when parsing OAuth parameters (ATTRIBUTE_KEYS + signature)

Returns:

  • (Array[Symbol])
[*ATTRIBUTE_KEYS, :signature].freeze

Constants included from Encoding

Encoding::UNRESERVED_CHARS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ClassMethods

body_hash, default_options, form_encoded?, form_pairs, from_request, generate_nonce, media_type, parse, parse_form_body

Methods included from Encoding

escape, unescape

Methods included from Params

#attributes, #expanded_params, #normalized_params, #signature_params, #url_params, #validate_option_keys!

Constructor Details

#initialize(method, url, params, oauth = {}, body = nil) ⇒ Header

Creates a new OAuth header

Parameters:

  • method (String, Symbol)
  • url (String, URI::Generic)
  • params (request_params)
  • oauth (oauth_options, String) (defaults to: {})
  • body (String, nil) (defaults to: nil)


89
90
91
92
93
94
95
# File 'lib/simple_oauth/header.rb', line 89

def initialize(method, url, params, oauth = {}, body = nil)
  @method = method.to_s.upcase
  @uri = normalize_uri(url)
  @params = params
  @body = body
  @options = build_options(oauth, body)
end

Instance Attribute Details

#bodyString? (readonly)

The raw request body for oauth_body_hash computation

Returns:

  • (String, nil)


58
59
60
# File 'lib/simple_oauth/header.rb', line 58

def body
  @body
end

#methodString (readonly)

The HTTP method for the request

Returns:

  • (String)


44
45
46
# File 'lib/simple_oauth/header.rb', line 44

def method
  @method
end

#optionsoauth_options (readonly)

The OAuth options including credentials and signature

Returns:

  • (oauth_options)


65
66
67
# File 'lib/simple_oauth/header.rb', line 65

def options
  @options
end

#paramsrequest_params (readonly)

The request parameters to be signed

Returns:

  • (request_params)


51
52
53
# File 'lib/simple_oauth/header.rb', line 51

def params
  @params
end

Class Method Details

.decodeString

Alias for unescape

Parameters:

  • value (String, _ToS)

Returns:

  • (String)


114
# File 'sig/simple_oauth.rbs', line 114

def self.decode: (String | _ToS value) -> String

.encodeString

Alias for escape

Parameters:

  • value (String, _ToS)

Returns:

  • (String)


108
# File 'sig/simple_oauth.rbs', line 108

def self.encode: (String | _ToS value) -> String

.escapeString

Percent-encodes a value according to OAuth specification

Parameters:

  • value (String, _ToS)

Returns:

  • (String)


105
# File 'sig/simple_oauth.rbs', line 105

def self.escape: (String | _ToS value) -> String

.unescapeString

Decodes a percent-encoded value

Parameters:

  • value (String, _ToS)

Returns:

  • (String)


111
# File 'sig/simple_oauth.rbs', line 111

def self.unescape: (String | _ToS value) -> String

Instance Method Details

#body_hash_valid?Boolean

Checks the body against the oauth_body_hash the header carries

Returns:

  • (Boolean)


227
228
229
230
231
232
233
# File 'lib/simple_oauth/header.rb', line 227

def body_hash_valid?
  claimed_body_hash = options[:body_hash]
  return true if body.nil? || claimed_body_hash.nil?

  digest = Signature.digest(options.fetch(:signature_method))
  OpenSSL.secure_compare(self.class.body_hash(body, digest), claimed_body_hash)
end

#build_options(oauth, body) ⇒ oauth_options

Builds OAuth options from input (hash or header string)

Parameters:

  • oauth (oauth_options, String)
  • body (String, nil)

Returns:

  • (oauth_options)


171
172
173
174
175
176
# File 'lib/simple_oauth/header.rb', line 171

def build_options(oauth, body)
  return self.class.parse(oauth) unless oauth.is_a?(Hash)

  overrides = oauth.transform_keys(&:to_sym)
  self.class.default_options(body, overrides.fetch(:signature_method, DEFAULT_SIGNATURE_METHOD)).merge(overrides)
end

#header_attributessigned_attributes_hash

Returns OAuth attributes including realm for Authorization header output

Returns:

  • (signed_attributes_hash)


196
197
198
199
200
# File 'lib/simple_oauth/header.rb', line 196

def header_attributes
  attrs = attributes
  attrs[:realm] = options.fetch(:realm) if options[:realm]
  attrs
end

#normalize_uri(url) ⇒ URI::Generic

Normalizes and parses a URL into a URI object

Parameters:

  • url (String, URI::Generic)

Returns:

  • (URI::Generic)


158
159
160
161
162
163
# File 'lib/simple_oauth/header.rb', line 158

def normalize_uri(url)
  URI.parse(url.to_s).tap do |uri|
    uri.normalize!
    uri.fragment = nil
  end
end

#normalized_attributesString

Builds the normalized OAuth attributes string for the Authorization header

Returns:

  • (String)


182
183
184
185
186
187
# File 'lib/simple_oauth/header.rb', line 182

def normalized_attributes
  signed_attributes
    .sort_by { |key, _| key }
    .map { |key, value| "#{key}=\"#{Header.escape(value)}\"" }
    .join(", ")
end

#secret(options) ⇒ String

Builds the secret string from consumer and token secrets

Parameters:

  • options (oauth_options)

Returns:

  • (String)


240
241
242
# File 'lib/simple_oauth/header.rb', line 240

def secret(options)
  options.values_at(:consumer_secret, :token_secret).map { |v| Header.escape(v) }.join("&")
end

#signatureString

Computes the OAuth signature using the configured signature method

Returns:

  • (String)


206
207
208
# File 'lib/simple_oauth/header.rb', line 206

def signature
  Signature.sign(options.fetch(:signature_method), signing_key(options), signature_base)
end

#signature_baseString

Builds the signature base string from method, URL, and params

Returns:

  • (String)


248
249
250
# File 'lib/simple_oauth/header.rb', line 248

def signature_base
  [method, url, normalized_params].map { |v| Header.escape(v) }.join("&")
end

#signed_attributessigned_attributes_hash

Returns the OAuth attributes including the signature

Returns:

  • (signed_attributes_hash)


147
148
149
# File 'lib/simple_oauth/header.rb', line 147

def signed_attributes
  header_attributes.merge(oauth_signature: signature)
end

#signing_key(options) ⇒ String?

The key for signing and verifying

Parameters:

  • options (oauth_options)

Returns:

  • (String, nil)


215
216
217
# File 'lib/simple_oauth/header.rb', line 215

def signing_key(options)
  Signature.rsa?(options.fetch(:signature_method)) ? options[:consumer_secret] : secret(options)
end

#to_sString

Returns the OAuth Authorization header string

Returns:

  • (String)


120
121
122
# File 'lib/simple_oauth/header.rb', line 120

def to_s
  "#{OAUTH_SCHEME} #{normalized_attributes}"
end

#urlString

Returns the normalized URL without query string or fragment

Returns:

  • (String)


105
106
107
108
109
# File 'lib/simple_oauth/header.rb', line 105

def url
  # String() takes whichever conversion the installed uri defines: it gained to_str in
  # 0.13, and the uri that ships with Ruby 3.2 offers only to_s
  String(@uri.dup.tap { |uri| uri.query = nil })
end

#valid?(secrets = {}) ⇒ Boolean

Validates the signature in the header against the provided secrets

Parameters:

  • secrets (oauth_options) (defaults to: {})

Returns:

  • (Boolean)


135
136
137
138
# File 'lib/simple_oauth/header.rb', line 135

def valid?(secrets = {})
  body_hash_valid? && Signature.verify(options.fetch(:signature_method), signing_key(options.merge(secrets)),
    signature_base, options.fetch(:signature))
end