diff --git a/config-sample.ini b/config-sample.ini index 90c7fa17e..939eaa7a5 100644 --- a/config-sample.ini +++ b/config-sample.ini @@ -28,6 +28,15 @@ keyPath= # expressjs shortcuts are supported: loopback(127.0.0.1/8, ::1/128), linklocal(169.254.0.0/16, fe80::/10), uniquelocal(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7) trustedReverseProxy=false + +[Session] +# Use this setting to constrain the current instance's "Path" value for the set cookies +# This can be useful, when you have several instances running on the same domain, under different paths (e.g. by using a reverse proxy). +# It prevents your instances from overwriting each others' cookies. +# e.g. if you have https://your-domain.com/triliumNext/instanceA and https://your-domain.com/triliumNext/instanceB +# you would want to set the cookiePath value to "/triliumNext/instanceA" for your first and "/triliumNext/instanceB" for your second instance +cookiePath=/ + [Sync] #syncServerHost= #syncServerTimeout= diff --git a/src/routes/csrf_protection.ts b/src/routes/csrf_protection.ts index 225651631..0ee03d467 100644 --- a/src/routes/csrf_protection.ts +++ b/src/routes/csrf_protection.ts @@ -1,11 +1,12 @@ import { doubleCsrf } from "csrf-csrf"; import sessionSecret from "../services/session_secret.js"; import { isElectron } from "../services/utils.js"; +import config from "../services/config.js"; const doubleCsrfUtilities = doubleCsrf({ getSecret: () => sessionSecret, cookieOptions: { - path: "", // empty, so cookie is valid only for the current path + path: config.Session.cookiePath, secure: false, sameSite: "strict", httpOnly: !isElectron // set to false for Electron, see https://github.com/TriliumNext/Notes/pull/966 diff --git a/src/routes/session_parser.ts b/src/routes/session_parser.ts index 90f415121..eaaf0ebe9 100644 --- a/src/routes/session_parser.ts +++ b/src/routes/session_parser.ts @@ -2,6 +2,7 @@ import session from "express-session"; import sessionFileStore from "session-file-store"; import sessionSecret from "../services/session_secret.js"; import dataDir from "../services/data_dir.js"; +import config from "../services/config.js"; const FileStore = sessionFileStore(session); const sessionParser = session({ @@ -9,7 +10,7 @@ const sessionParser = session({ resave: false, // true forces the session to be saved back to the session store, even if the session was never modified during the request. saveUninitialized: false, // true forces a session that is "uninitialized" to be saved to the store. A session is uninitialized when it is new but not modified. cookie: { - // path: "/", + path: config.Session.cookiePath, httpOnly: true, maxAge: 24 * 60 * 60 * 1000 // in milliseconds }, diff --git a/src/services/config.ts b/src/services/config.ts index dbbf644b5..b529d4792 100644 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -32,6 +32,9 @@ export interface TriliumConfig { keyPath: string; trustedReverseProxy: boolean | string; }; + Session: { + cookiePath: string; + } Sync: { syncServerHost: string; syncServerTimeout: string; @@ -76,6 +79,11 @@ const config: TriliumConfig = { process.env.TRILIUM_NETWORK_TRUSTEDREVERSEPROXY || iniConfig.Network.trustedReverseProxy || false }, + Session: { + cookiePath: + process.env.TRILIUM_SESSION_COOKIEPATH || iniConfig?.Session?.cookiePath || "/" + }, + Sync: { syncServerHost: process.env.TRILIUM_SYNC_SERVER_HOST || iniConfig?.Sync?.syncServerHost || "",