From 3c8723a40410da227e5200a8580dcf2698acac2c Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Mon, 10 Feb 2025 08:33:31 +0100 Subject: [PATCH 1/4] feat(config): add Cookies.cookiePath option to config defaults to "/" as previously set by default options --- config-sample.ini | 9 +++++++++ src/services/config.ts | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/config-sample.ini b/config-sample.ini index 90c7fa17e..58d5c87ba 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 + +[Cookies] +# 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/services/config.ts b/src/services/config.ts index dbbf644b5..7dff7ad0a 100644 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -32,6 +32,9 @@ export interface TriliumConfig { keyPath: string; trustedReverseProxy: boolean | string; }; + Cookies: { + cookiePath: string; + } Sync: { syncServerHost: string; syncServerTimeout: string; @@ -76,6 +79,11 @@ const config: TriliumConfig = { process.env.TRILIUM_NETWORK_TRUSTEDREVERSEPROXY || iniConfig.Network.trustedReverseProxy || false }, + Cookies: { + cookiePath: + process.env.TRILIUM_COOKIES_COOKIEPATH || iniConfig?.Cookies?.cookiePath || "/" + }, + Sync: { syncServerHost: process.env.TRILIUM_SYNC_SERVER_HOST || iniConfig?.Sync?.syncServerHost || "", From a600568ab8477b4431f36d7850c5428409672d9d Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Mon, 10 Feb 2025 08:35:01 +0100 Subject: [PATCH 2/4] feat(session_parser): use cookiePath from config --- src/routes/session_parser.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/session_parser.ts b/src/routes/session_parser.ts index 90f415121..b99882d0b 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.Cookies.cookiePath, httpOnly: true, maxAge: 24 * 60 * 60 * 1000 // in milliseconds }, From b6d73df92e70c642935da85e8a95d3305f81c0c8 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Mon, 10 Feb 2025 08:48:40 +0100 Subject: [PATCH 3/4] feat(csrf_protection): use cookiePath from config --- src/routes/csrf_protection.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/csrf_protection.ts b/src/routes/csrf_protection.ts index 225651631..e9cd55f26 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.Cookies.cookiePath, secure: false, sameSite: "strict", httpOnly: !isElectron // set to false for Electron, see https://github.com/TriliumNext/Notes/pull/966 From 62f8f8f1a7c6215229a57d3a884d17ec19ec40f4 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Mon, 10 Feb 2025 19:07:21 +0100 Subject: [PATCH 4/4] refactor(config): rename Cookies to Session as requested in PR #1155 --- config-sample.ini | 2 +- src/routes/csrf_protection.ts | 2 +- src/routes/session_parser.ts | 2 +- src/services/config.ts | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config-sample.ini b/config-sample.ini index 58d5c87ba..939eaa7a5 100644 --- a/config-sample.ini +++ b/config-sample.ini @@ -29,7 +29,7 @@ keyPath= trustedReverseProxy=false -[Cookies] +[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. diff --git a/src/routes/csrf_protection.ts b/src/routes/csrf_protection.ts index e9cd55f26..0ee03d467 100644 --- a/src/routes/csrf_protection.ts +++ b/src/routes/csrf_protection.ts @@ -6,7 +6,7 @@ import config from "../services/config.js"; const doubleCsrfUtilities = doubleCsrf({ getSecret: () => sessionSecret, cookieOptions: { - path: config.Cookies.cookiePath, + 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 b99882d0b..eaaf0ebe9 100644 --- a/src/routes/session_parser.ts +++ b/src/routes/session_parser.ts @@ -10,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: config.Cookies.cookiePath, + 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 7dff7ad0a..b529d4792 100644 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -32,7 +32,7 @@ export interface TriliumConfig { keyPath: string; trustedReverseProxy: boolean | string; }; - Cookies: { + Session: { cookiePath: string; } Sync: { @@ -79,9 +79,9 @@ const config: TriliumConfig = { process.env.TRILIUM_NETWORK_TRUSTEDREVERSEPROXY || iniConfig.Network.trustedReverseProxy || false }, - Cookies: { + Session: { cookiePath: - process.env.TRILIUM_COOKIES_COOKIEPATH || iniConfig?.Cookies?.cookiePath || "/" + process.env.TRILIUM_SESSION_COOKIEPATH || iniConfig?.Session?.cookiePath || "/" }, Sync: {