From 8c6277a281a5ffc721c45f89ec1997a10855bbbf Mon Sep 17 00:00:00 2001 From: Max Sanna Date: Mon, 26 Jan 2026 17:28:50 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8D=AA=20refactor:=20Secure=20Cookie=20Se?= =?UTF-8?q?tting=20for=20Localhost=20OAuth=20Sessions=20(#11518)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Added check for secure cookies when running in production mode on localhost * Applied copilot's suggestions --- api/server/socialLogins.js | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/api/server/socialLogins.js b/api/server/socialLogins.js index bad64eee77..cf67fa9436 100644 --- a/api/server/socialLogins.js +++ b/api/server/socialLogins.js @@ -15,6 +15,38 @@ const { } = require('~/strategies'); const { getLogStores } = require('~/cache'); +/** + * Determines if secure cookies should be used. + * Only use secure cookies in production when not on localhost. + * @returns {boolean} + */ +function shouldUseSecureCookie() { + const isProduction = process.env.NODE_ENV === 'production'; + const domainServer = process.env.DOMAIN_SERVER || ''; + + let hostname = ''; + if (domainServer) { + try { + const normalized = /^https?:\/\//i.test(domainServer) + ? domainServer + : `http://${domainServer}`; + const url = new URL(normalized); + hostname = (url.hostname || '').toLowerCase(); + } catch { + // Fallback: treat DOMAIN_SERVER directly as a hostname-like string + hostname = domainServer.toLowerCase(); + } + } + + const isLocalhost = + hostname === 'localhost' || + hostname === '127.0.0.1' || + hostname === '::1' || + hostname.endsWith('.localhost'); + + return isProduction && !isLocalhost; +} + /** * Configures OpenID Connect for the application. * @param {Express.Application} app - The Express application instance. @@ -22,7 +54,6 @@ const { getLogStores } = require('~/cache'); */ async function configureOpenId(app) { logger.info('Configuring OpenID Connect...'); - const isProduction = process.env.NODE_ENV === 'production'; const sessionExpiry = Number(process.env.SESSION_EXPIRY) || DEFAULT_SESSION_EXPIRY; const sessionOptions = { secret: process.env.OPENID_SESSION_SECRET, @@ -31,7 +62,7 @@ async function configureOpenId(app) { store: getLogStores(CacheKeys.OPENID_SESSION), cookie: { maxAge: sessionExpiry, - secure: isProduction, + secure: shouldUseSecureCookie(), }, }; app.use(session(sessionOptions)); @@ -88,7 +119,6 @@ const configureSocialLogins = async (app) => { process.env.SAML_SESSION_SECRET ) { logger.info('Configuring SAML Connect...'); - const isProduction = process.env.NODE_ENV === 'production'; const sessionExpiry = Number(process.env.SESSION_EXPIRY) || DEFAULT_SESSION_EXPIRY; const sessionOptions = { secret: process.env.SAML_SESSION_SECRET, @@ -97,7 +127,7 @@ const configureSocialLogins = async (app) => { store: getLogStores(CacheKeys.SAML_SESSION), cookie: { maxAge: sessionExpiry, - secure: isProduction, + secure: shouldUseSecureCookie(), }, }; app.use(session(sessionOptions));