Creating Signature and Nonce for Oauth (Ruby)

Creating Signature and Nonce for OAuth (Ruby)

For the signature:

def sign( key, base_string )
digest = OpenSSL::Digest::Digest.new( 'sha1' )
hmac = OpenSSL::HMAC.digest( digest, key, base_string )
Base64.encode64( hmac ).chomp.gsub( /\n/, '' )
end#def

You don't have to generate the nonce from the timestamp, but it can make sense since the timestamp is obviously unique, so it makes a good starting input for any randomisation function.

I use this, (that I got from another question on here and modified)

def nonce
rand(10 ** 30).to_s.rjust(30,'0')
end#def

but you can use anything that generates a unique string.

See this gist by erikeldridge on github and Beginner’s Guide to OAuth for more

Edit

I've since found there's a better way to generate random strings in the Ruby standard library, SecureRandom.

How a OAuth1.0 Signature is generated

I found a metod for creating an Oauth 1.0 signture.It requires all parameters of the api request to be hashed in SHA1 algorithm.

private string CreateOauthSignature
(string resourceUrl, string oauthNonce, string oauthTimestamp ,
SortedDictionary<string, string> requestParameters)
{
//Add the standard oauth parameters to the sorted list
requestParameters.Add("oauth_consumer_key", consumerKey);
requestParameters.Add("oauth_nonce", oauthNonce);
requestParameters.Add("oauth_signature_method", OauthSignatureMethod);
requestParameters.Add("oauth_timestamp", oauthTimestamp);
requestParameters.Add("oauth_token", accessToken);
requestParameters.Add("oauth_version", OauthVersion);

var sigBaseString = requestParameters.ToWebString();

var signatureBaseString = string.Concat
("GET", "&", Uri.EscapeDataString(resourceUrl), "&",
Uri.EscapeDataString(sigBaseString.ToString()));

//Using this base string, encrypt the data using a composite of the
//secret keys and the HMAC-SHA1 algorithm.
var compositeKey = string.Concat(Uri.EscapeDataString(consumerKeySecret), "&",
Uri.EscapeDataString(accessTokenSecret));

string oauthSignature;
using (var hasher = new HMACSHA1(Encoding.ASCII.GetBytes(compositeKey)))
{
oauthSignature = Convert.ToBase64String(
hasher.ComputeHash(Encoding.ASCII.GetBytes(signatureBaseString)));
}
return oauthSignature;
}

The ToWebstring() is an Extension method for converting the Sorted dictionary to a web string and encoding the special characters.After creating the signature this can be included in the authorization header of the Http request along with the other header parameters viz. nonce,timestamp,access token etc.

What's the point of a timestamp in OAuth if a Nonce can only be used one time?

The timestamp is used for allowing the server to optimize their storage of nonces. Basically, consider the read nonce to be the combination of the timestamp and random string. But by having a separate timestamp component, the server can implement a time-based restriction using a short window (say, 15 minutes) and limit the amount of storage it needs. Without timestamps, the server will need infinite storage to keep every nonce ever used.

Let's say you decide to allow up to 15 minutes time difference between your clock and the client's and are keeping track of the nonce values in a database table. The unique key for the table is going to be a combination of 'client identifier', 'access token', 'nonce', and 'timestamp'. When a new request comes in, check that the timestamp is within 15 minutes of your clock then lookup that combination in your table. If found, reject the call, otherwise add that to your table and return the requested resource. Every time you add a new nonce to the table, delete any record for that 'client identifier' and 'access token' combination with timestamp older than 15 minutes.

How do I use the oauth gem to validate a token passed into the request?

I finally figured out the answer to this, so I'll put it here in the hopes of helping someone in the future.

Once you've retrieved the AccessToken and ClientApplication objects from the underlying database and checked the nonce and timestamp, verifying the signature is as easy as:

signature = OAuth::Signature.verify(request, {}) do |sigblock|
[token.secret, ca.secret]
end

If the signature checks out, signature will be true. Beware - if you're behind an http proxy such as nginx, the SERVER_PORT environment variable may not be correctly set for https requests and you may have to set it manually. If this (or any other seemingly tiny part of the request) is off, it can cause the signature verification to fail even if the request is valid.

Do we really need oauth_nonce?

Keys are unique but don't change often. A nonce on the other hand needs to be unique per request.

Consider the following scenario. Prerequisites are: An attacker can spy on your communication but does not know any secrets. If there is no nonce, he can do a replay attack: He can simply duplicate and resend any of your previous requests, because he knows the requests you already send are valid.

A nonce prevents this, as the server checks all recently used nonces (there is a time limit) and does not accept any nonce twice.



Related Topics



Leave a reply



Submit