Skip to content

Instantly share code, notes, and snippets.

@pironim
Forked from erikeldridge/example.rb
Last active August 29, 2015 14:12
Show Gist options
  • Select an option

  • Save pironim/f0c4b72946edeaa9cb23 to your computer and use it in GitHub Desktop.

Select an option

Save pironim/f0c4b72946edeaa9cb23 to your computer and use it in GitHub Desktop.

Revisions

  1. erikeldridge revised this gist Apr 29, 2010. 2 changed files with 51 additions and 69 deletions.
    14 changes: 7 additions & 7 deletions example.rb
    Original file line number Diff line number Diff line change
    @@ -1,17 +1,17 @@
    require 'oauth_util.rb'
    require 'net/http'

    o = OauthUtil.new
    o.consumer_key = 'exampleduxcswe2xfvjnspf';
    o.consumer_secret = 'examplejWpm';

    url = 'http://api.netflix.com/oauth/request_token'
    o.consumer_key = 'examplek9SGJUTUpocjZ5QjBJmQ9WVdrOVVFNHdSR2x1TkhFbWNHbzlNQS0tJnM9Y29uc3VtkZXJzZWNyZXQmeD0yYg--';
    o.consumer_secret = 'exampled88d4109c63e778dsadcdd5c1875814977';

    require 'net/http'
    url = 'http://query.yahooapis.com/v1/yql?q=select%20*%20from%20social.updates.search%20where%20query%3D%22search%20terms%22&diagnostics=true';

    parsed_url = URI.parse( url )

    Net::HTTP.start( parsed_url.host ) {|http|
    req = Net::HTTP::Get.new( "#{parsed_url.path}?#{o.sign( url ).to_query_string() }" )
    Net::HTTP.start( parsed_url.host ) { | http |
    req = Net::HTTP::Get.new "#{ parsed_url.path }?#{ o.sign(parsed_url).query_string }"
    response = http.request(req)
    print response.body
    print response.read_body
    }
    106 changes: 44 additions & 62 deletions oauth_util.rb
    Original file line number Diff line number Diff line change
    @@ -4,12 +4,14 @@
    # Usage: see example.rb below

    require 'uri'
    require 'cgi'
    require 'openssl'
    require 'base64'

    class OauthUtil

    attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method, :sig_method, :oauth_version, :callback_url, :params
    attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method,
    :sig_method, :oauth_version, :callback_url, :params, :req_url, :base_str

    def initialize
    @consumer_key = ''
    @@ -20,96 +22,76 @@ def initialize
    @sig_method = 'HMAC-SHA1'
    @oauth_version = '1.0'
    @callback_url = ''
    @params = []
    end

    # openssl::random_bytes returns non-word chars, which need to be removed. using alt method to get consistent length
    # openssl::random_bytes returns non-word chars, which need to be removed. using alt method to get length
    # ref http://snippets.dzone.com/posts/show/491
    def generate_nonce
    def nonce
    Array.new( 5 ) { rand(256) }.pack('C*').unpack('H*').first
    end

    def percent_encode( string )

    # ref http://snippets.dzone.com/posts/show/1260
    URI.escape( string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") )
    end

    # sort (very important as it affects the signature), concat, and percent encode
    # @ref http://oauth.net/core/1.0/#rfc.section.9.1.1
    # @ref http://oauth.net/core/1.0/#9.2.1
    # @ref http://oauth.net/core/1.0/#rfc.section.A.5.1
    def normalize_req_params( params )
    percent_encode( params.sort().join( '&' ) )
    end

    # @ref http://oauth.net/core/1.0/#rfc.section.9.1.2
    def construct_req_url( url)
    parsed_url = URI.parse( url )
    parsed_url.scheme + '://' + parsed_url.host + parsed_url.path
    return URI.escape( string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") ).gsub('*', '%2A')
    end

    # @ref http://oauth.net/core/1.0/#rfc.section.9.2
    def generate_sig( args )
    key = percent_encode( args[:consumer_secret] ) + '&' + percent_encode( args[:token_secret] )
    text = args[:base_str]
    def signature
    key = percent_encode( @consumer_secret ) + '&' + percent_encode( @token_secret )

    # credit: http://blog.nathanielbibler.com/post/63031273/openssl-hmac-vs-ruby-hmac-benchmarks
    # ref: http://blog.nathanielbibler.com/post/63031273/openssl-hmac-vs-ruby-hmac-benchmarks
    digest = OpenSSL::Digest::Digest.new( 'sha1' )
    raw_sig = OpenSSL::HMAC.digest( digest, key, text )
    hmac = OpenSSL::HMAC.digest( digest, key, @base_str )

    # ref http://groups.google.com/group/oauth-ruby/browse_thread/thread/9110ed8c8f3cae81
    Base64.encode64( raw_sig ).chomp.gsub( /\n/, '' )
    Base64.encode64( hmac ).chomp.gsub( /\n/, '' )
    end

    def to_query_string
    @params.find_all{ | item | item =~ /oauth_.*/ }.join( '&' )
    end

    def to_header_string
    # sort (very important as it affects the signature), concat, and percent encode
    # @ref http://oauth.net/core/1.0/#rfc.section.9.1.1
    # @ref http://oauth.net/core/1.0/#9.2.1
    # @ref http://oauth.net/core/1.0/#rfc.section.A.5.1
    def query_string
    pairs = []

    # format string as key1="val1", key2="val2" ...
    @params.find_all{ | item | item =~ /oauth_.*/ }.each{ | item |
    pair = '%s="%s"' % item.split( '=' )
    pairs.push( pair )
    @params.sort.each { | key, val |
    pairs.push( "#{ percent_encode( key ) }=#{ percent_encode( val.to_s ) }" )
    }
    pairs.join( ', ' )
    pairs.join '&'
    end

    def sign( url )

    parsed_url = URI.parse( url )
    # organize params & create signature
    def sign( parsed_url )

    # basic oauth params formatted as strings in array so we can easily sort
    @params.push( 'oauth_consumer_key=' + @consumer_key )
    @params.push( 'oauth_nonce=' + generate_nonce() )
    @params.push( 'oauth_signature_method=' + @sig_method )
    @params.push( 'oauth_timestamp=' + Time.now.to_i.to_s )
    @params.push( 'oauth_version=' + @oauth_version )
    @params = {
    'oauth_consumer_key' => @consumer_key,
    'oauth_nonce' => nonce,
    'oauth_signature_method' => @sig_method,
    'oauth_timestamp' => Time.now.to_i.to_s,
    'oauth_version' => @oauth_version
    }

    # if params passed in, add them & replace defaults
    # if url has query, merge key/values into params obj overwriting defaults
    if parsed_url.query
    @params = @params | parsed_url.query.split( '&' )
    @params.merge! CGI.parse( parsed_url.query )
    end

    # elems for base str
    normal_req_params = normalize_req_params( params )

    # @ref http://oauth.net/core/1.0/#rfc.section.9.1.2
    req_url = parsed_url.scheme + '://' + parsed_url.host + parsed_url.path

    # create base str
    base_str = [ @req_method, percent_encode( req_url ), normal_req_params ].join( '&' )

    # sign
    signature = generate_sig({
    :base_str => base_str,
    :consumer_secret => @consumer_secret,
    :token_secret => @token_secret
    })
    @req_url = parsed_url.scheme + '://' + parsed_url.host + parsed_url.path

    # create base str. make it an object attr for ez debugging
    # ref http://oauth.net/core/1.0/#anchor14
    @base_str = [
    @req_method,
    percent_encode( req_url ),

    # normalization is just x-www-form-urlencoded
    percent_encode( query_string )

    ].join( '&' )

    @params.push( 'oauth_signature=' + percent_encode( signature ) )
    # add signature
    @params[ 'oauth_signature' ] = signature

    return self
    end
  2. erikeldridge revised this gist Apr 29, 2010. 2 changed files with 2 additions and 2 deletions.
    2 changes: 1 addition & 1 deletion example.rb
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    require 'oauth_util.rb'

    o = Oauth.new
    o = OauthUtil.new
    o.consumer_key = 'exampleduxcswe2xfvjnspf';
    o.consumer_secret = 'examplejWpm';

    2 changes: 1 addition & 1 deletion oauth_util.rb
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@
    require 'openssl'
    require 'base64'

    class Oauth
    class OauthUtil

    attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method, :sig_method, :oauth_version, :callback_url, :params

  3. erikeldridge created this gist Apr 29, 2010.
    17 changes: 17 additions & 0 deletions example.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    require 'oauth_util.rb'

    o = Oauth.new
    o.consumer_key = 'exampleduxcswe2xfvjnspf';
    o.consumer_secret = 'examplejWpm';

    url = 'http://api.netflix.com/oauth/request_token'

    require 'net/http'

    parsed_url = URI.parse( url )

    Net::HTTP.start( parsed_url.host ) {|http|
    req = Net::HTTP::Get.new( "#{parsed_url.path}?#{o.sign( url ).to_query_string() }" )
    response = http.request(req)
    print response.body
    }
    116 changes: 116 additions & 0 deletions oauth_util.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,116 @@
    # A utility for signing an url using OAuth in a way that's convenient for debugging
    # Note: the standard Ruby OAuth lib is here http://github.com/mojodna/oauth
    # License: http://gist.github.com/375593
    # Usage: see example.rb below

    require 'uri'
    require 'openssl'
    require 'base64'

    class Oauth

    attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method, :sig_method, :oauth_version, :callback_url, :params

    def initialize
    @consumer_key = ''
    @consumer_secret = ''
    @token = ''
    @token_secret = ''
    @req_method = 'GET'
    @sig_method = 'HMAC-SHA1'
    @oauth_version = '1.0'
    @callback_url = ''
    @params = []
    end

    # openssl::random_bytes returns non-word chars, which need to be removed. using alt method to get consistent length
    # ref http://snippets.dzone.com/posts/show/491
    def generate_nonce
    Array.new( 5 ) { rand(256) }.pack('C*').unpack('H*').first
    end

    def percent_encode( string )

    # ref http://snippets.dzone.com/posts/show/1260
    URI.escape( string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") )
    end

    # sort (very important as it affects the signature), concat, and percent encode
    # @ref http://oauth.net/core/1.0/#rfc.section.9.1.1
    # @ref http://oauth.net/core/1.0/#9.2.1
    # @ref http://oauth.net/core/1.0/#rfc.section.A.5.1
    def normalize_req_params( params )
    percent_encode( params.sort().join( '&' ) )
    end

    # @ref http://oauth.net/core/1.0/#rfc.section.9.1.2
    def construct_req_url( url)
    parsed_url = URI.parse( url )
    parsed_url.scheme + '://' + parsed_url.host + parsed_url.path
    end

    # @ref http://oauth.net/core/1.0/#rfc.section.9.2
    def generate_sig( args )
    key = percent_encode( args[:consumer_secret] ) + '&' + percent_encode( args[:token_secret] )
    text = args[:base_str]

    # credit: http://blog.nathanielbibler.com/post/63031273/openssl-hmac-vs-ruby-hmac-benchmarks
    digest = OpenSSL::Digest::Digest.new( 'sha1' )
    raw_sig = OpenSSL::HMAC.digest( digest, key, text )

    # ref http://groups.google.com/group/oauth-ruby/browse_thread/thread/9110ed8c8f3cae81
    Base64.encode64( raw_sig ).chomp.gsub( /\n/, '' )
    end

    def to_query_string
    @params.find_all{ | item | item =~ /oauth_.*/ }.join( '&' )
    end

    def to_header_string
    pairs = []

    # format string as key1="val1", key2="val2" ...
    @params.find_all{ | item | item =~ /oauth_.*/ }.each{ | item |
    pair = '%s="%s"' % item.split( '=' )
    pairs.push( pair )
    }
    pairs.join( ', ' )
    end

    def sign( url )

    parsed_url = URI.parse( url )

    # basic oauth params formatted as strings in array so we can easily sort
    @params.push( 'oauth_consumer_key=' + @consumer_key )
    @params.push( 'oauth_nonce=' + generate_nonce() )
    @params.push( 'oauth_signature_method=' + @sig_method )
    @params.push( 'oauth_timestamp=' + Time.now.to_i.to_s )
    @params.push( 'oauth_version=' + @oauth_version )

    # if params passed in, add them & replace defaults
    if parsed_url.query
    @params = @params | parsed_url.query.split( '&' )
    end

    # elems for base str
    normal_req_params = normalize_req_params( params )

    # @ref http://oauth.net/core/1.0/#rfc.section.9.1.2
    req_url = parsed_url.scheme + '://' + parsed_url.host + parsed_url.path

    # create base str
    base_str = [ @req_method, percent_encode( req_url ), normal_req_params ].join( '&' )

    # sign
    signature = generate_sig({
    :base_str => base_str,
    :consumer_secret => @consumer_secret,
    :token_secret => @token_secret
    })

    @params.push( 'oauth_signature=' + percent_encode( signature ) )

    return self
    end
    end