Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating unique token on the fly with Rails

Tags:

I want to generate a token in my controller for a user in the "user_info_token" column. However, I want to check that no user currently has that token. Would this code suffice?

  begin     @new_token = SecureRandom.urlsafe_base64      user = User.find_by_user_info_token(@new_token)    end while user != nil     @seller.user_info_token = @new_token  

Or is there a much cleaner way to do this?

like image 651
Alain Goldman Avatar asked Sep 01 '13 01:09

Alain Goldman


1 Answers

If your token is long enough and generated by a cryptographically secure [pseudo-]random number generator, then you do not need to verify that the token is unique. You do not need to generate tokens in a loop.

16 raw source bytes is long enough for this effective guarantee. When formatted for URL-safety, the result will be longer.

# Base-64 (url-safe) encoded bytes, 22 characters long SecureRandom.urlsafe_base64(16)  # Base-36 encoded bytes, naturally url-safe, ~25 characters long SecureRandom.hex(16).to_i(16).to_s(36)  # Base-16 encoded bytes, naturally url-safe, 32 characters long SecureRandom.hex(16) 

This is because the probability that the 16-byte or 128-bit token is nonunique is so vanishingly small that it is virtually zero. There is only a 50% chance of there being any repetitions after approximately 264 = 18,446,744,073,709,551,616 = 1.845 x 1019 tokens have been generated. If you start generating one billion tokens per second, it will take approximately 264/(109*3600*24*365.25) = 600 years until there is a 50% chance of there having occurred any repetitions at all.

But you're not generating one billion tokens per second. Let's be generous and suppose you were generating one token per second. The time frame until a 50% chance of even one collision becomes 600 billion years. The planet will have been swallowed up by the sun long before then.

like image 91
yfeldblum Avatar answered Dec 05 '22 04:12

yfeldblum