module Signet::OAuth1
def self.encode value
-
(String)- The percent-encoded value.
Parameters:
-
value(Symbol, #to_str) -- The value to be encoded.
def self.encode value value = value.to_s if value.is_a? Symbol Addressable::URI.encode_component( value, Addressable::URI::CharacterClasses::UNRESERVED ) end
def self.extract_credential_key_option credential_type, options
-
(String)- The credential key value.
Parameters:
-
credential_type(Symbol) --
def self.extract_credential_key_option credential_type, options # Normalize key to String to allow indifferent access. options = options.to_h.transform_keys(&:to_s) credential_key = "#{credential_type}_credential_key" credential = "#{credential_type}_credential" if options[credential_key] credential_key = options[credential_key] elsif options[credential] require "signet/oauth_1/credential" unless options[credential].respond_to? :key raise TypeError, "Expected Signet::OAuth1::Credential, " \ "got #{options[credential].class}." end credential_key = options[credential].key elsif options["client"] require "signet/oauth_1/client" unless options["client"].is_a? ::Signet::OAuth1::Client raise TypeError, "Expected Signet::OAuth1::Client, got #{options['client'].class}." end credential_key = options["client"].send credential_key else credential_key = nil end if !credential_key.nil? && !credential_key.is_a?(String) raise TypeError, "Expected String, got #{credential_key.class}." end credential_key end
def self.extract_credential_secret_option credential_type, options
-
(String)- The credential secret value.
Parameters:
-
credential_type(Symbol) --
def self.extract_credential_secret_option credential_type, options # Normalize key to String to allow indifferent access. options = options.to_h.transform_keys(&:to_s) credential_secret = "#{credential_type}_credential_secret" credential = "#{credential_type}_credential" if options[credential_secret] credential_secret = options[credential_secret] elsif options[credential] require "signet/oauth_1/credential" unless options[credential].respond_to? :secret raise TypeError, "Expected Signet::OAuth1::Credential, " \ "got #{options[credential].class}." end credential_secret = options[credential].secret elsif options["client"] require "signet/oauth_1/client" unless options["client"].is_a? ::Signet::OAuth1::Client raise TypeError, "Expected Signet::OAuth1::Client, got #{options['client'].class}." end credential_secret = options["client"].send credential_secret else credential_secret = nil end if !credential_secret.nil? && !credential_secret.is_a?(String) raise TypeError, "Expected String, got #{credential_secret.class}." end credential_secret end
def self.generate_authorization_header parameters, realm = nil
-
(String)- TheAuthorizationheader.
Parameters:
-
realm(String) -- -
parameters(Enumerable) -- The OAuth parameter list.
def self.generate_authorization_header parameters, realm = nil if !parameters.is_a?(Enumerable) || parameters.is_a?(String) raise TypeError, "Expected Enumerable, got #{parameters.class}." end parameter_list = parameters.map do |k, v| if k == "realm" raise ArgumentError, 'The "realm" parameter must be specified as a separate argument.' end "#{encode k}=\"#{encode v}\"" end if realm realm = realm.gsub '"', '\"' parameter_list.unshift "realm=\"#{realm}\"" end "OAuth #{parameter_list.join ', '}" end
def self.generate_authorization_uri authorization_uri, options = {}
-
(String)- The authorization URI to redirect the user to.
Parameters:
-
authorization_uri(Addressable::URI, String, #to_str) --
def self.generate_authorization_uri authorization_uri, options = {} options = { callback: nil, additional_parameters: {} }.merge(options) temporary_credential_key = extract_credential_key_option :temporary, options parsed_uri = Addressable::URI.parse(authorization_uri).dup query_values = parsed_uri.query_values || {} if options[:additional_parameters] query_values = query_values.merge( options[:additional_parameters].each_with_object({}) { |(k, v), h| h[k] = v } ) end query_values["oauth_token"] = temporary_credential_key if temporary_credential_key query_values["oauth_callback"] = options[:callback] if options[:callback] parsed_uri.query_values = query_values parsed_uri.normalize.to_s end
def self.generate_base_string method, uri, parameters
-
(String)- The signature base string.
Parameters:
-
parameters(Enumerable) -- The OAuth parameter list. -
uri(Addressable::URI, String, #to_str) -- The URI. -
method(String) -- The HTTP method.
def self.generate_base_string method, uri, parameters raise TypeError, "Expected Enumerable, got #{parameters.class}." unless parameters.is_a? Enumerable method = method.to_s.upcase parsed_uri = Addressable::URI.parse uri uri = Addressable::URI.new( scheme: parsed_uri.normalized_scheme, authority: parsed_uri.normalized_authority, path: parsed_uri.path, query: parsed_uri.query, fragment: parsed_uri.fragment ) uri_parameters = uri.query_values(Array) || [] uri = uri.omit(:query, :fragment).to_s merged_parameters = uri_parameters.concat(parameters.map { |k, v| [k, v] }) parameter_string = normalize_parameters merged_parameters [ encode(method), encode(uri), encode(parameter_string) ].join("&") end
def self.generate_nonce
-
(String)- A random nonce.
def self.generate_nonce SecureRandom.random_bytes(16).unpack("H*").join end
def self.generate_timestamp
-
(String)- The current timestamp.
def self.generate_timestamp Time.now.to_i.to_s end
def self.normalize_parameters parameters
-
(String)- The normalized parameter list.
Parameters:
-
parameters(Enumerable) -- The OAuth parameter list.
def self.normalize_parameters parameters raise TypeError, "Expected Enumerable, got #{parameters.class}." unless parameters.is_a? Enumerable parameter_list = parameters.map do |k, v| next if k == "oauth_signature" # This is probably the wrong place to try to exclude the realm "#{encode k}=#{encode v}" end parameter_list.compact.sort.join "&" end
def self.parse_authorization_header field_value
parameters. Parameter keys and values are decoded according to the
Parses an
Authorization header into its component#
def self.parse_authorization_header field_value raise TypeError, "Expected String, got #{field_value.class}." unless field_value.is_a? String auth_scheme = field_value[/^([-._0-9a-zA-Z]+)/, 1] case auth_scheme when /^OAuth$/i # Other token types may be supported eventually pairs = Signet.parse_auth_param_list(field_value[/^OAuth\s+(.*)$/i, 1]) (pairs.each_with_object [] do |(k, v), accu| if k != "realm" k = unencode k v = unencode v end accu << [k, v] end) else raise ParseError, "Parsing non-OAuth Authorization headers is out of scope." end end
def self.parse_form_encoded_credentials body
-
(Signet::OAuth1::Credential)- The OAuth credentials.
Parameters:
-
body(String) -- The response body.
def self.parse_form_encoded_credentials body raise TypeError, "Expected String, got #{body.class}." unless body.is_a? String Signet::OAuth1::Credential.new( Addressable::URI.form_unencode(body) ) end
def self.sign_parameters method, uri, parameters,
-
(String)- The signature.
Parameters:
-
token_credential_secret(String) -- -
client_credential_secret(String) -- The client credential secret. -
parameters(Enumerable) -- The OAuth parameter list. -
uri(Addressable::URI, String, #to_str) -- The URI. -
method(String) -- The HTTP method.
def self.sign_parameters method, uri, parameters, client_credential_secret, token_credential_secret = nil # Technically, the token_credential_secret parameter here may actually # be a temporary credential secret when obtaining a token credential # for the first time base_string = generate_base_string method, uri, parameters parameters = parameters.to_h.transform_keys(&:to_s) signature_method = parameters["oauth_signature_method"] case signature_method when "HMAC-SHA1" require "signet/oauth_1/signature_methods/hmac_sha1" Signet::OAuth1::HMACSHA1.generate_signature base_string, client_credential_secret, token_credential_secret when "RSA-SHA1" require "signet/oauth_1/signature_methods/rsa_sha1" Signet::OAuth1::RSASHA1.generate_signature base_string, client_credential_secret, token_credential_secret when "PLAINTEXT" require "signet/oauth_1/signature_methods/plaintext" Signet::OAuth1::PLAINTEXT.generate_signature base_string, client_credential_secret, token_credential_secret else raise NotImplementedError, "Unsupported signature method: #{signature_method}" end end
def self.unencode value
-
(String)- The unencoded value.
Parameters:
-
value(#to_str) --
def self.unencode value Addressable::URI.unencode_component value end
def self.unsigned_resource_parameters options = {}
-
(Array)-
Parameters:
-
options(Hash) --
def self.unsigned_resource_parameters options = {} options = { signature_method: "HMAC-SHA1", two_legged: false }.merge(options) client_credential_key = extract_credential_key_option :client, options raise ArgumentError, "Missing :client_credential_key parameter." if client_credential_key.nil? unless options[:two_legged] token_credential_key = extract_credential_key_option :token, options raise ArgumentError, "Missing :token_credential_key parameter." if token_credential_key.nil? end parameters = [ ["oauth_consumer_key", client_credential_key], ["oauth_signature_method", options[:signature_method]], ["oauth_timestamp", generate_timestamp], ["oauth_nonce", generate_nonce], ["oauth_version", "1.0"] ] parameters << ["oauth_token", token_credential_key] unless options[:two_legged] # No additional parameters allowed here parameters end
def self.unsigned_temporary_credential_parameters options = {}
-
(Array)-
Parameters:
-
options(Hash) --
def self.unsigned_temporary_credential_parameters options = {} options = { callback: ::Signet::OAuth1::OUT_OF_BAND, signature_method: "HMAC-SHA1", additional_parameters: [] }.merge(options) client_credential_key = extract_credential_key_option :client, options raise ArgumentError, "Missing :client_credential_key parameter." if client_credential_key.nil? parameters = [ ["oauth_consumer_key", client_credential_key], ["oauth_signature_method", options[:signature_method]], ["oauth_timestamp", generate_timestamp], ["oauth_nonce", generate_nonce], ["oauth_version", "1.0"], ["oauth_callback", options[:callback]] ] # Works for any Enumerable options[:additional_parameters].each do |key, value| parameters << [key, value] end parameters end
def self.unsigned_token_credential_parameters options = {}
-
(Array)-
Parameters:
-
options(Hash) --
def self.unsigned_token_credential_parameters options = {} options = { signature_method: "HMAC-SHA1", verifier: nil }.merge(options) client_credential_key = extract_credential_key_option :client, options temporary_credential_key = extract_credential_key_option :temporary, options raise ArgumentError, "Missing :client_credential_key parameter." if client_credential_key.nil? raise ArgumentError, "Missing :temporary_credential_key parameter." if temporary_credential_key.nil? raise ArgumentError, "Missing :verifier parameter." if options[:verifier].nil? [ ["oauth_consumer_key", client_credential_key], ["oauth_token", temporary_credential_key], ["oauth_signature_method", options[:signature_method]], ["oauth_timestamp", generate_timestamp], ["oauth_nonce", generate_nonce], ["oauth_verifier", options[:verifier]], ["oauth_version", "1.0"] ] end