From 0a054e6b541fd5ab470bf025665f5f7d2acedaa0 Mon Sep 17 00:00:00 2001 From: Vivek Joshi <37882929+vivekjoshi556@users.noreply.github.com> Date: Mon, 27 May 2024 20:03:11 +0530 Subject: [PATCH] fix: Parse Server option `extendSessionOnUse` not working for session lengths < 24 hours (#9113) --- spec/Auth.spec.js | 21 +++++++++++++++++++++ src/Auth.js | 17 +++++++++++++---- src/Options/Definitions.js | 3 ++- src/Options/docs.js | 2 +- src/Options/index.js | 2 +- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index 632623a871..9f10cf781e 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -260,3 +260,24 @@ describe('Auth', () => { }); }); }); + +describe('extendSessionOnUse', () => { + it(`shouldUpdateSessionExpiry()`, async () => { + const { shouldUpdateSessionExpiry } = require('../lib/Auth'); + let update = new Date(Date.now() - 86410 * 1000); + + const res = shouldUpdateSessionExpiry( + { sessionLength: 86460 }, + { updatedAt: update } + ); + + update = new Date(Date.now() - 43210 * 1000); + const res2 = shouldUpdateSessionExpiry( + { sessionLength: 86460 }, + { updatedAt: update } + ); + + expect(res).toBe(true); + expect(res2).toBe(false); + }); +}); diff --git a/src/Auth.js b/src/Auth.js index f21ba96c6c..c5351fe9fc 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -67,6 +67,17 @@ function nobody(config) { return new Auth({ config, isMaster: false }); } +/** + * Checks whether session should be updated based on last update time & session length. + */ +function shouldUpdateSessionExpiry(config, session) { + const resetAfter = config.sessionLength / 2; + const lastUpdated = new Date(session?.updatedAt); + const skipRange = new Date(); + skipRange.setTime(skipRange.getTime() - resetAfter * 1000); + return lastUpdated <= skipRange; +} + const throttle = {}; const renewSessionIfNeeded = async ({ config, session, sessionToken }) => { if (!config?.extendSessionOnUse) { @@ -88,10 +99,7 @@ const renewSessionIfNeeded = async ({ config, session, sessionToken }) => { const { results } = await query.execute(); session = results[0]; } - const lastUpdated = new Date(session?.updatedAt); - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); - if (lastUpdated > yesterday || !session) { + if (!shouldUpdateSessionExpiry(config, session) || !session) { return; } const expiresAt = config.generateSessionExpiresAt(); @@ -579,6 +587,7 @@ module.exports = { maintenance, nobody, readOnly, + shouldUpdateSessionExpiry, getAuthForSessionToken, getAuthForLegacySessionToken, findUsersWithAuthData, diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 27baac2258..1fd028a81d 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -259,7 +259,8 @@ module.exports.ParseServerOptions = { }, extendSessionOnUse: { env: 'PARSE_SERVER_EXTEND_SESSION_ON_USE', - help: 'Whether Parse Server should automatically extend a valid session by the sessionLength', + help: + "Whether Parse Server should automatically extend a valid session by the sessionLength. In order to reduce the number of session updates in the database, a session will only be extended when a request is received after at least half of the current session's lifetime has passed.", action: parsers.booleanParser, default: false, }, diff --git a/src/Options/docs.js b/src/Options/docs.js index 219fc2e5a9..d9d4a4ad26 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -47,7 +47,7 @@ * @property {String} encryptionKey Key for encrypting your files * @property {Boolean} enforcePrivateUsers Set to true if new users should be created without public read and write access. * @property {Boolean} expireInactiveSessions Sets whether we should expire the inactive sessions, defaults to true. If false, all new sessions are created with no expiration date. - * @property {Boolean} extendSessionOnUse Whether Parse Server should automatically extend a valid session by the sessionLength + * @property {Boolean} extendSessionOnUse Whether Parse Server should automatically extend a valid session by the sessionLength. In order to reduce the number of session updates in the database, a session will only be extended when a request is received after at least half of the current session's lifetime has passed. * @property {String} fileKey Key for your files * @property {Adapter} filesAdapter Adapter module for the files sub-system * @property {FileUploadOptions} fileUpload Options for file uploads diff --git a/src/Options/index.js b/src/Options/index.js index 067ac15ff3..f7263e8786 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -228,7 +228,7 @@ export interface ParseServerOptions { /* Session duration, in seconds, defaults to 1 year :DEFAULT: 31536000 */ sessionLength: ?number; - /* Whether Parse Server should automatically extend a valid session by the sessionLength + /* Whether Parse Server should automatically extend a valid session by the sessionLength. In order to reduce the number of session updates in the database, a session will only be extended when a request is received after at least half of the current session's lifetime has passed. :DEFAULT: false */ extendSessionOnUse: ?boolean; /* Default value for limit option on queries, defaults to `100`.