11

I'm looking to access SmugMug's API from my application to grab users' albums and images (the users have been authenticated via ruby's OmniAuth).

According to SmugMug's OAuth API, OAuth requires six parameters.

I can get the token with OmniAuth, and the timestamp should be easy (Time.now.to_i right?). There are two things that I don't know how to generate -- the oauth_nonce and the oauth_signature.

According to the oauth docs, I generate the nonce via the timestamp, but how exactly would I do that? Does it need to be a certain length and limited to certain characters?

And of course the signature. How would I generate a HMAC-SHA1 sig with ruby? I know the oauth gem can do it, but I'd rather generate it myself to use with OmniAuth. Looking at the code, I'm having trouble deciphering how the oauth gem generates the sig.

Thank you for any help.

kmurph79
  • 1,192
  • 3
  • 13
  • 28

3 Answers3

15

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.

GEOCHET
  • 21,119
  • 15
  • 74
  • 98
ian
  • 12,003
  • 9
  • 51
  • 107
  • I wanted to say thanks again as that gist you linked to has been incredibly helpful. However, I had trouble getting it working with 1.9.2, and couldn't quite figure out why -- have you solved this problem? – kmurph79 Jun 01 '11 at 12:27
  • I wrote this on 1.9.2 so if it's not working then perhaps it's something else? Do you have any error messages to share? I had to write a lot of logging statements before getting it to work, anything with encryption will require that and tests or you'll find it hard to track down the problem. – ian Jun 01 '11 at 15:50
  • Thanks for the reply. I was talking of the gist you linked to, but I figured out the problem -- CGI.parse was turning the values of the url parameters into an array (which it didn't do in 1.8.7), which was screwing up my API call. All is working. Thanks for your time. – kmurph79 Jun 02 '11 at 10:31
  • `nonce = OpenSSL::Random.random_bytes 12` – Amozoss Jul 25 '15 at 15:29
5

A nonce can also be simply a large-ish, properly random number - for example, using Ruby's SecureRandom class (don't use 'rand'):

require 'securerandom'

...

nonce = SecureRandom.hex()

This generates a 16-byte random number in hex format.

JohnK
  • 406
  • 4
  • 6
  • One question. This solution could be perfect, but it has one main problem. How can I save all nonces? I simply cant. A solution must be based on timestamp, anyway. See this link. http://stackoverflow.com/questions/6865690/whats-the-point-of-a-timestamp-in-oauth-if-a-nonce-can-only-be-used-one-time – Andrea Reginato Nov 23 '12 at 09:07
  • You need a nonce cache, yes. The nonce cache is bounded by time. – JohnK Mar 30 '13 at 23:19
1

Why you don't just use the Oauth ruby gems to do that ?

shingara
  • 46,608
  • 11
  • 99
  • 105
  • Thanks for the reply. I want to use OmniAuth (and have it set up) and am not sure how I would integrate it with oauth. OmniAuth gets me everything but these two things so I'd rather just write them myself. – kmurph79 Dec 25 '10 at 03:39
  • omniauth do all you want to you. no need to check the oauth params – shingara Dec 26 '10 at 11:48