diff --git a/package-lock.json b/package-lock.json index 52b06b2e0..e3be9aa17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -532,6 +532,11 @@ "precond": "0.2" } }, + "bagpipe": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz", + "integrity": "sha1-40HRZPyyTN8E6n4Ft2XsEMiupqE=" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -3448,8 +3453,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-keys": { "version": "1.1.1", @@ -4088,6 +4092,11 @@ "path-parse": "^1.0.6" } }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, "retry-request": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.0.0.tgz", @@ -4362,6 +4371,53 @@ "send": "0.17.1" } }, + "session-file-store": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/session-file-store/-/session-file-store-1.3.1.tgz", + "integrity": "sha512-6W8N+ziXDoT3oNKqLP+38QMO1CELfWHhn7/G/T/Bj2BXLKnkJCCFqWIb9E50Rr3ENtzuxy3FT9KHy39+skBubg==", + "requires": { + "bagpipe": "^0.3.5", + "fs-extra": "^8.0.1", + "object-assign": "^4.1.1", + "retry": "^0.12.0", + "write-file-atomic": "1.3.1" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "graceful-fs": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "write-file-atomic": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.1.tgz", + "integrity": "sha1-fUW6MjFjKN0ex9kPYOvA2EW7dZo=", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + } + } + }, "set-blocking": { "version": "2.0.0", "resolved": false, @@ -4554,6 +4610,11 @@ "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, "smtp-connection": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", @@ -5126,6 +5187,11 @@ "crypto-random-string": "^1.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index cffb48a49..854e101e5 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "s3-block-read-stream": "^0.5.0", "safetydance": "^0.7.1", "semver": "^6.1.1", + "session-file-store": "^1.3.1", "showdown": "^1.9.0", "speakeasy": "^2.0.0", "split": "^1.0.1", diff --git a/src/paths.js b/src/paths.js index 2ee33ea47..d3bb1d05c 100644 --- a/src/paths.js +++ b/src/paths.js @@ -39,6 +39,9 @@ exports = module.exports = { DYNDNS_INFO_FILE: path.join(baseDir(), 'platformdata/dyndns-info.json'), VERSION_FILE: path.join(baseDir(), 'platformdata/VERSION'), + SESSION_SECRET_FILE: path.join(baseDir(), 'boxdata/session.secret'), + SESSION_DIR: path.join(baseDir(), 'platformdata/sessions'), + // this is not part of appdata because an icon may be set before install APP_ICONS_DIR: path.join(baseDir(), 'boxdata/appicons'), MAIL_DATA_DIR: path.join(baseDir(), 'boxdata/mail'), diff --git a/src/server.js b/src/server.js index d753f7fa8..c277a1904 100644 --- a/src/server.js +++ b/src/server.js @@ -18,7 +18,9 @@ var accesscontrol = require('./accesscontrol.js'), middleware = require('./middleware'), passport = require('passport'), path = require('path'), + paths = require('./paths.js'), routes = require('./routes/index.js'), + safe = require('safetydance'), settings = require('./settings.js'), ws = require('ws'); @@ -57,6 +59,15 @@ function initializeExpressSync() { var router = new express.Router(); router.del = router.delete; // amend router.del for readability further on + // load or generate the session secret + var sessionSecret = safe.fs.readFileSync(paths.SESSION_SECRET_FILE, 'utf8'); + if (!sessionSecret) { + sessionSecret = hat(128); + safe.fs.writeFileSync(paths.SESSION_SECRET_FILE, sessionSecret); + } + + var SessionFileStore = require('session-file-store')(middleware.session); + app // the timeout middleware will respond with a 503. the request itself cannot be 'aborted' and will continue // search for req.clearTimeout in route handlers to see places where this timeout is reset @@ -66,9 +77,12 @@ function initializeExpressSync() { .use(middleware.cookieParser()) .use(middleware.cors({ origins: [ '*' ], allowCredentials: false })) .use(middleware.session({ - secret: hat(128), // we only use the session during oauth, and already have an in-memory session store, so we can safely change that during restarts - resave: true, - saveUninitialized: true, + secret: sessionSecret, + saveUninitialized: false, + resave: false, + store: new SessionFileStore({ + path: paths.SESSION_DIR + }), cookie: { path: '/', httpOnly: true,