express-session: Extend session lifetime if user is active

This commit is contained in:
Richard Hansen 2021-12-23 01:45:38 -05:00
parent 9c1f52f1b0
commit 692749d1cf
9 changed files with 68 additions and 10 deletions

View file

@ -998,6 +998,7 @@ const handleClientReady = async (socket, message) => {
readOnlyId: sessionInfo.readOnlyPadId,
readonly: sessionInfo.readonly,
serverTimestamp: Date.now(),
sessionRefreshInterval: settings.cookie.sessionRefreshInterval,
userId: sessionInfo.author,
abiwordAvailable: settings.abiwordAvailable(),
sofficeAvailable: settings.sofficeAvailable(),

View file

@ -176,8 +176,10 @@ exports.restartServer = async () => {
app.use(cookieParser(settings.sessionKey, {}));
sessionStore = new SessionStore();
sessionStore = new SessionStore(settings.cookie.sessionRefreshInterval);
exports.sessionMiddleware = expressSession({
propagateTouch: true,
rolling: true,
secret: settings.sessionKey,
store: sessionStore,
resave: false,

View file

@ -105,6 +105,19 @@ exports.expressCreateServer = (hookName, args, cb) => {
express.sessionMiddleware(req, {}, next);
});
io.use((socket, next) => {
socket.conn.on('packet', (packet) => {
// Tell express-session that the session is still active. The session store can use these
// touch events to defer automatic session cleanup, and if express-session is configured with
// rolling=true the cookie's expiration time will be renewed. (Note that WebSockets does not
// have a standard mechanism for periodically updating the browser's cookies, so the browser
// will not see the new cookie expiration time unless it makes a new HTTP request or the new
// cookie value is sent to the client in a custom socket.io message.)
if (socket.request.session != null) socket.request.session.touch();
});
next();
});
// var socketIOLogger = log4js.getLogger("socket.io");
// Debug logging now has to be set at an environment level, this is stupid.
// https://github.com/Automattic/socket.io/wiki/Migrating-to-1.0

View file

@ -106,5 +106,12 @@ exports.expressCreateServer = (hookName, args, cb) => {
}));
});
// The client occasionally polls this endpoint to get an updated expiration for the express_sid
// cookie. This handler must be installed after the express-session middleware.
args.app.put('/_extendExpressSessionLifetime', (req, res) => {
// express-session automatically calls req.session.touch() so we don't need to do it here.
res.json({status: 'ok'});
});
return cb();
};

View file

@ -323,6 +323,7 @@ exports.cookie = {
*/
sameSite: 'Lax',
sessionLifetime: 10 * 24 * 60 * 60 * 1000,
sessionRefreshInterval: 1 * 24 * 60 * 60 * 1000,
};
/*

View file

@ -293,6 +293,11 @@ const handshake = async () => {
} else if (!receivedClientVars && obj.type === 'CLIENT_VARS') {
receivedClientVars = true;
window.clientVars = obj.data;
if (window.clientVars.sessionRefreshInterval) {
const ping =
() => $.ajax('../_extendExpressSessionLifetime', {method: 'PUT'}).catch(() => {});
setInterval(ping, window.clientVars.sessionRefreshInterval);
}
} else if (obj.disconnect) {
padconnectionstatus.disconnected(obj.disconnect);
socket.disconnect();

View file

@ -111,6 +111,12 @@ const handleClientVars = (message) => {
// save the client Vars
window.clientVars = message.data;
if (window.clientVars.sessionRefreshInterval) {
const ping =
() => $.ajax('../../_extendExpressSessionLifetime', {method: 'PUT'}).catch(() => {});
setInterval(ping, window.clientVars.sessionRefreshInterval);
}
// load all script that doesn't work without the clientVars
BroadcastSlider = require('./broadcast_slider')
.loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded);