Permalink
Browse files

Merge pull request #18347 from robertomiranda/has_secure_token_base62

Switching SecureTokens to Base58
  • Loading branch information...
guilleiguaran committed Jan 9, 2015
2 parents 6907fcd + 47316fe commit d8b8a726e7b7290b380b3b1274484b08449deaf2
Showing with 8 additions and 32 deletions.
  1. +8 −18 activerecord/lib/active_record/secure_token.rb
  2. +0 −14 activerecord/test/cases/secure_token_test.rb
@@ -13,35 +13,25 @@ module ClassMethods
#
# user = User.new
# user.save
# user.token # => "44539a6a59835a4ee9d7b112"
# user.auth_token # => "e2426a93718d1817a43abbaa"
# user.token # => "4kUgL2pdQMSCQtjE"
# user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
# user.regenerate_token # => true
# user.regenerate_auth_token # => true
#
# SecureRandom is used to generate the 24-character unique token, so collisions are highly unlikely.
# We'll check to see if the generated token has been used already using #exists?, and retry up to 10
# times to find another unused token. After that a RuntimeError is raised if the problem persists.
# SecureRandom::base58 is used to generate the 24-character unique token, so collisions are highly unlikely.
#
# Note that it's still possible to generate a race condition in the database in the same way that
# validates_presence_of can. You're encouraged to add a unique index in the database to deal with
# this even more unlikely scenario.
def has_secure_token(attribute = :token)
# Load securerandom only when has_secure_key is used.
require 'securerandom'
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token(attribute) }
before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token(attribute)) }
require 'active_support/core_ext/securerandom'
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) }
end
def generate_unique_secure_token(attribute)
10.times do |i|
SecureRandom.hex(12).tap do |token|
if exists?(attribute => token)
raise "Couldn't generate a unique token in 10 attempts!" if i == 9
else
return token
end
end
end
def generate_unique_secure_token
SecureRandom.base58(24)
end
end
end
@@ -22,18 +22,4 @@ def test_regenerating_the_secure_token
assert_not_equal @user.token, old_token
assert_not_equal @user.auth_token, old_auth_token
end
def test_raise_after_ten_unsuccessful_attempts_to_generate_a_unique_token
User.stubs(:exists?).returns(*Array.new(10, true))
assert_raises(RuntimeError) do
@user.save
end
end
def test_return_unique_token_after_nine_unsuccessful_attempts
User.stubs(:exists?).returns(*Array.new(10) { |i| i == 9 ? false : true })
@user.save
assert_not_nil @user.token
assert_not_nil @user.auth_token
end
end

0 comments on commit d8b8a72

Please sign in to comment.