From b7d2edc7dc4e1e80c1ab1ef8161a7e08fbf50b02 Mon Sep 17 00:00:00 2001 From: Sam Saffron Date: Wed, 22 Feb 2017 12:36:58 -0500 Subject: [PATCH] FIX: allow some auth token misses prior to clearing cookie It appears that in some cases ios queues up requests up front and "releases" them when tab gets focus, this allows for a certain number of cookie misses for this case. Otherwise you get logged off. --- lib/auth/default_current_user_provider.rb | 12 +++++++++++- .../auth/default_current_user_provider_spec.rb | 10 ++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/auth/default_current_user_provider.rb b/lib/auth/default_current_user_provider.rb index 0b905f61323..f35e97c4638 100644 --- a/lib/auth/default_current_user_provider.rb +++ b/lib/auth/default_current_user_provider.rb @@ -12,6 +12,11 @@ class Auth::DefaultCurrentUserProvider TOKEN_COOKIE ||= "_t".freeze PATH_INFO ||= "PATH_INFO".freeze COOKIE_ATTEMPTS_PER_MIN ||= 10 + # allow up to 20 cookie misses, this may be the case + # when requests are delayed in weird ways, for example + # on mobile when coming back online + MAX_COOKIE_MISSES ||= 10 + COOKIE_MISS_KEY ||= "cookie_misses" # do all current user initialization here def initialize(env) @@ -136,7 +141,12 @@ class Auth::DefaultCurrentUserProvider end if !user && cookies.key?(TOKEN_COOKIE) - cookies.delete(TOKEN_COOKIE) + cookie_miss_key = COOKIE_MISS_KEY + cookies[TOKEN_COOKIE] + misses = $redis.get(cookie_miss_key).to_i + 1 + $redis.setex(cookie_miss_key, 1.hour.to_i, misses) + if misses > MAX_COOKIE_MISSES + cookies.delete(TOKEN_COOKIE) + end end end diff --git a/spec/components/auth/default_current_user_provider_spec.rb b/spec/components/auth/default_current_user_provider_spec.rb index e666d4c8460..6bfec747383 100644 --- a/spec/components/auth/default_current_user_provider_spec.rb +++ b/spec/components/auth/default_current_user_provider_spec.rb @@ -201,9 +201,15 @@ describe Auth::DefaultCurrentUserProvider do it "correctly removes invalid cookies" do - cookies = {"_t" => "BAAAD"} - provider('/').refresh_session(nil, {}, cookies) + cookies = {"_t" => SecureRandom.hex} + (Auth::DefaultCurrentUserProvider::MAX_COOKIE_MISSES).times do + provider('/').refresh_session(nil, {}, cookies) + end + + expect(cookies.key?("_t")).to eq(true) + + provider('/').refresh_session(nil, {}, cookies) expect(cookies.key?("_t")).to eq(false) end