From 9e7f8b85dd12de07986f44ac3d874bd035d86ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Fri, 3 Apr 2020 22:43:21 +0200 Subject: [PATCH] Add config for auto logout after browser inactivity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- config/config.sample.php | 9 +++++++ core/src/session-heartbeat.js | 50 ++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/config/config.sample.php b/config/config.sample.php index 00e3a6779f..268838a176 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -251,6 +251,15 @@ $CONFIG = [ */ 'session_keepalive' => true, +/** + * Enable or disable the automatic logout after session_lifetime, even if session + * keepalive is enabled. This will make sure that an inactive browser will be logged out + * even if requests to the server might extend the session lifetime. + * + * Defaults to ``false`` + */ +'auto_logout' => false, + /** * Enforce token authentication for clients, which blocks requests using the user * password for enhanced security. Users need to generate tokens in personal settings diff --git a/core/src/session-heartbeat.js b/core/src/session-heartbeat.js index a941720d85..4678982d59 100644 --- a/core/src/session-heartbeat.js +++ b/core/src/session-heartbeat.js @@ -21,18 +21,21 @@ import $ from 'jquery' import { emit } from '@nextcloud/event-bus' +import { loadState } from '@nextcloud/initial-state' +import { getCurrentUser } from '@nextcloud/auth' import { generateUrl } from './OC/routing' -import OC from './OC' -import { setToken as setRequestToken } from './OC/requesttoken' +import { setToken as setRequestToken, getToken as getRequestToken } from './OC/requesttoken' + +const config = loadState('core', 'config') /** * session heartbeat (defaults to enabled) * @returns {boolean} */ const keepSessionAlive = () => { - return OC.config.session_keepalive === undefined - || !!OC.config.session_keepalive + return config.session_keepalive === undefined + || !!config.session_keepalive } /** @@ -41,8 +44,8 @@ const keepSessionAlive = () => { */ const getInterval = () => { let interval = NaN - if (OC.config.session_lifetime) { - interval = Math.floor(OC.config.session_lifetime / 2) + if (config.session_lifetime) { + interval = Math.floor(config.session_lifetime / 2) } // minimum one minute, max 24 hours, default 15 minutes @@ -83,11 +86,46 @@ const startPolling = () => { return interval } +const registerAutoLogout = () => { + if (!config.auto_logout || !getCurrentUser()) { + return + } + + let lastActive = Date.now() + window.addEventListener('mousemove', e => { + lastActive = Date.now() + localStorage.setItem('lastActive', lastActive) + }) + + window.addEventListener('touchstart', e => { + lastActive = Date.now() + localStorage.setItem('lastActive', lastActive) + }) + + window.addEventListener('storage', e => { + if (e.key !== 'lastActive') { + return + } + lastActive = e.newValue + }) + + setInterval(function() { + const timeout = Date.now() - config.session_lifetime * 1000 + if (lastActive < timeout) { + console.info('Inactivity timout reached, logging out') + const logoutUrl = generateUrl('/logout') + '?requesttoken=' + getRequestToken() + window.location = logoutUrl + } + }, 1000) +} + /** * Calls the server periodically to ensure that session and CSRF * token doesn't expire */ export const initSessionHeartBeat = () => { + registerAutoLogout() + if (!keepSessionAlive()) { console.info('session heartbeat disabled') return