Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions lib/devise/models/rememberable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,13 @@ def after_remembered
end

def remember_me?(token, generated_at)
# TODO: Normalize the JSON type coercion along with the Timeoutable hook
# in a single place https://github.com/heartcombo/devise/blob/ffe9d6d406e79108cf32a2c6a1d0b3828849c40b/lib/devise/hooks/timeoutable.rb#L14-L18
if generated_at.is_a?(String)
# Normalize cookie/session JSON type coercion the same way Timeoutable
# does for last_request_at (Integer from to_i, Float/numeric strings
# from to_f / to_json).
case generated_at
when Integer, Float
generated_at = Time.at(generated_at).utc
when String
generated_at = time_from_json(generated_at)
end

Expand All @@ -122,7 +126,7 @@ def remember_me?(token, generated_at)
private

def time_from_json(value)
if value =~ /\A\d+\.\d+\Z/
if value =~ /\A\d+(?:\.\d+)?\Z/
Time.at(value.to_f)
else
Time.parse(value) rescue nil
Expand Down
17 changes: 17 additions & 0 deletions test/models/rememberable_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,23 @@ def create_resource
assert_equal user, User.serialize_from_cookie(user.to_key, user.authenticatable_salt, Time.now.utc.to_f.to_json)
end

test 'serialize from cookie should accept Integer and Float timestamps from JSON coercion' do
user = create_user
user.remember_me!
assert_equal user, User.serialize_from_cookie(user.to_key, user.authenticatable_salt, Time.now.utc.to_f)

# Integer seconds truncate subseconds, so keep remember_created_at clearly earlier.
user.update_attribute(:remember_created_at, 1.minute.ago)
assert_equal user, User.serialize_from_cookie(user.to_key, user.authenticatable_salt, Time.now.utc.to_i)
end

test 'serialize from cookie should accept an Integer-only numeric String timestamp' do
user = create_user
user.remember_me!
user.update_attribute(:remember_created_at, 1.minute.ago)
assert_equal user, User.serialize_from_cookie(user.to_key, user.authenticatable_salt, Time.now.utc.to_i.to_s)
end

test 'serialize from cookie should return nil with invalid datetime' do
user = create_user
user.remember_me!
Expand Down