FEATURE: refresh session cookie at most once an hour
This feature ensures session cookie lifespan is extended when user is online. Also decreases session timeout from 90 to 60 days. Ensures all users (including logged on ones) get expiring sessions.
This commit is contained in:
parent
a9207dafa7
commit
df535c6346
|
@ -44,6 +44,7 @@ class ApplicationController < ActionController::Base
|
|||
before_filter :redirect_to_login_if_required
|
||||
before_filter :check_xhr
|
||||
after_filter :add_readonly_header
|
||||
after_filter :perform_refresh_session
|
||||
|
||||
layout :set_layout
|
||||
|
||||
|
@ -59,6 +60,10 @@ class ApplicationController < ActionController::Base
|
|||
response.headers['Discourse-Readonly'] = 'true' if Discourse.readonly_mode?
|
||||
end
|
||||
|
||||
def perform_refresh_session
|
||||
refresh_session(current_user)
|
||||
end
|
||||
|
||||
def slow_platform?
|
||||
request.user_agent =~ /Android/
|
||||
end
|
||||
|
|
|
@ -1048,7 +1048,7 @@ end
|
|||
# trust_level_locked :boolean default(FALSE), not null
|
||||
# staged :boolean default(FALSE), not null
|
||||
# first_seen_at :datetime
|
||||
# auth_token_created_at :datetime
|
||||
# auth_token_updated_at :datetime
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
@ -909,7 +909,7 @@ en:
|
|||
post_undo_action_window_mins: "Number of minutes users are allowed to undo recent actions on a post (like, flag, etc)."
|
||||
must_approve_users: "Staff must approve all new user accounts before they are allowed to access the site. WARNING: enabling this for a live site will revoke access for existing non-staff users!"
|
||||
pending_users_reminder_delay: "Notify moderators if new users have been waiting for approval for longer than this many hours. Set to -1 to disable notifications."
|
||||
maximum_session_age: "User will remain logged in for n hours."
|
||||
maximum_session_age: "User will remain logged in for n hours since last visit"
|
||||
ga_tracking_code: "OBSOLETE: Google analytics (ga.js) tracking code code, eg: UA-12345678-9; see http://google.com/analytics"
|
||||
ga_domain_name: "OBSOLETE: Google analytics (ga.js) domain name, eg: mysite.com; see http://google.com/analytics"
|
||||
ga_universal_tracking_code: "Google Universal Analytics (analytics.js) tracking code code, eg: UA-12345678-9; see http://google.com/analytics"
|
||||
|
|
|
@ -305,7 +305,7 @@ login:
|
|||
min: -1
|
||||
default: 8
|
||||
maximum_session_age:
|
||||
default: 2160
|
||||
default: 1440
|
||||
min: 1
|
||||
max: 175200
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class RenameAuthTokenCreatedAt < ActiveRecord::Migration
|
||||
def change
|
||||
rename_column :users, :auth_token_created_at, :auth_token_updated_at
|
||||
end
|
||||
end
|
|
@ -16,6 +16,10 @@ class Auth::CurrentUserProvider
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# optional interface to be called to refresh cookies etc if needed
|
||||
def refresh_session(user,session,cookies)
|
||||
end
|
||||
|
||||
# api has special rights return true if api was detected
|
||||
def is_api?
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -36,7 +36,10 @@ class Auth::DefaultCurrentUserProvider
|
|||
current_user = nil
|
||||
|
||||
if auth_token && auth_token.length == 32
|
||||
current_user = User.where(auth_token: auth_token).where('auth_token_created_at IS NULL OR auth_token_created_at > ?', SiteSetting.maximum_session_age.hours.ago).first
|
||||
current_user = User.where(auth_token: auth_token)
|
||||
.where('auth_token_updated_at IS NULL OR auth_token_updated_at > ?',
|
||||
SiteSetting.maximum_session_age.hours.ago)
|
||||
.first
|
||||
end
|
||||
|
||||
if current_user && (current_user.suspended? || !current_user.active)
|
||||
|
@ -61,9 +64,16 @@ class Auth::DefaultCurrentUserProvider
|
|||
@env[CURRENT_USER_KEY] = current_user
|
||||
end
|
||||
|
||||
def refresh_session(user, session, cookies)
|
||||
if user && (!user.auth_token_updated_at || user.auth_token_updated_at <= 1.hour.ago)
|
||||
user.update_column(:auth_token_updated_at, Time.zone.now)
|
||||
cookies[TOKEN_COOKIE] = { value: user.auth_token, httponly: true, expires: SiteSetting.maximum_session_age.hours.from_now }
|
||||
end
|
||||
end
|
||||
|
||||
def log_on_user(user, session, cookies)
|
||||
user.auth_token = SecureRandom.hex(16)
|
||||
user.auth_token_created_at = Time.zone.now
|
||||
user.auth_token_updated_at = Time.zone.now
|
||||
user.save!
|
||||
cookies[TOKEN_COOKIE] = { value: user.auth_token, httponly: true, expires: SiteSetting.maximum_session_age.hours.from_now }
|
||||
make_developer_admin(user)
|
||||
|
|
|
@ -30,6 +30,10 @@ module CurrentUser
|
|||
current_user_provider.current_user
|
||||
end
|
||||
|
||||
def refresh_session(user)
|
||||
current_user_provider.refresh_session(user,session,cookies)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_user_provider
|
||||
|
|
|
@ -72,5 +72,29 @@ describe Auth::DefaultCurrentUserProvider do
|
|||
expect(provider("/topic/anything/goes", method: "POST").should_update_last_seen?).to eq(true)
|
||||
expect(provider("/topic/anything/goes", method: "GET").should_update_last_seen?).to eq(true)
|
||||
end
|
||||
|
||||
it "correctly renews session once an hour" do
|
||||
SiteSetting.maximum_session_age = 3
|
||||
user = Fabricate(:user)
|
||||
provider('/').log_on_user(user, {}, {})
|
||||
|
||||
freeze_time 2.hours.from_now
|
||||
cookies = {}
|
||||
provider("/", "HTTP_COOKIE" => "_t=#{user.auth_token}").refresh_session(user, {}, cookies)
|
||||
|
||||
expect(user.auth_token_updated_at - Time.now).to eq(0)
|
||||
|
||||
end
|
||||
|
||||
it "correctly expires session" do
|
||||
SiteSetting.maximum_session_age = 2
|
||||
user = Fabricate(:user)
|
||||
provider('/').log_on_user(user, {}, {})
|
||||
|
||||
expect(provider("/", "HTTP_COOKIE" => "_t=#{user.auth_token}").current_user.id).to eq(user.id)
|
||||
|
||||
freeze_time 3.hours.from_now
|
||||
expect(provider("/", "HTTP_COOKIE" => "_t=#{user.auth_token}").current_user).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue