From 5c85d249dc07251f7814256add4544175c3bc0d9 Mon Sep 17 00:00:00 2001 From: Uzlopak Date: Fri, 9 Sep 2022 02:15:49 +0200 Subject: [PATCH] simplify cookie handling (#166) --- lib/cookie.js | 48 --------------------------------------- lib/fastifySession.js | 11 +++------ lib/getCookieOpts.js | 35 ++++++++++++++++++++++++++++ lib/isConnectionSecure.js | 8 +++++++ lib/session.js | 4 ++-- 5 files changed, 48 insertions(+), 58 deletions(-) delete mode 100644 lib/cookie.js create mode 100644 lib/getCookieOpts.js create mode 100644 lib/isConnectionSecure.js diff --git a/lib/cookie.js b/lib/cookie.js deleted file mode 100644 index 4889f7f..0000000 --- a/lib/cookie.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict' - -class Cookie { - constructor (cookieOpts) { - this.originalMaxAge = cookieOpts.originalMaxAge || cookieOpts.maxAge || null - this.path = cookieOpts.path || '/' - this.httpOnly = cookieOpts.httpOnly !== undefined ? cookieOpts.httpOnly : true - this.secure = cookieOpts.secure - this.expires = getExpires(cookieOpts, this.originalMaxAge) - this.sameSite = cookieOpts.sameSite || null - this.domain = cookieOpts.domain || null - } - - options (secureConnection) { - let secure = this.secure - let sameSite = this.sameSite - if (secure === 'auto') { - if (secureConnection === true) { - secure = true - } else { - sameSite = 'Lax' - secure = false - } - } else { - secure = this.secure - } - return { - path: this.path, - httpOnly: this.httpOnly, - secure, - expires: this.expires, - sameSite, - domain: this.domain - } - } -} - -function getExpires (cookieOpts, maxAge) { - if (maxAge) { - return new Date(Date.now() + maxAge) - } else if (cookieOpts.expires) { - return new Date(cookieOpts.expires) - } - return null -} - -module.exports = Cookie -module.exports.getExpires = getExpires diff --git a/lib/fastifySession.js b/lib/fastifySession.js index 339a5bc..407e781 100644 --- a/lib/fastifySession.js +++ b/lib/fastifySession.js @@ -4,6 +4,7 @@ const fp = require('fastify-plugin') const idGenerator = require('./idGenerator')() const Store = require('./store') const Session = require('./session') +const isConnectionSecure = require('./isConnectionSecure') function fastifySession (fastify, options, next) { const error = checkOptions(options) @@ -165,7 +166,7 @@ function fastifySession (fastify, options, next) { const cookieSessionId = getCookieSessionId(request) const saveSession = shouldSaveSession(request, cookieSessionId, saveUninitializedSession, rollingSessions) - const isInsecureConnection = cookieOpts.secure === true && !isConnectionSecure(request) + const isInsecureConnection = cookieOpts.secure === true && isConnectionSecure(request) === false if (!saveSession || isInsecureConnection) { // if a session cookie is set, but has a different ID, clear it if (cookieSessionId && cookieSessionId !== session.encryptedSessionId) { @@ -183,7 +184,7 @@ function fastifySession (fastify, options, next) { reply.setCookie( cookieName, hasCookiePrefix ? `${cookiePrefix}${session.encryptedSessionId}` : session.encryptedSessionId, - session.cookie.options(isConnectionSecure(request)) + session.cookie ) done() }) @@ -219,12 +220,6 @@ function fastifySession (fastify, options, next) { return opts } - function isConnectionSecure (request) { - return ( - request.raw.socket?.encrypted === true || request.headers['x-forwarded-proto'] === 'https' - ) - } - function shouldSaveSession (request, cookieId, saveUninitializedSession, rollingSessions) { return cookieId !== request.session.encryptedSessionId ? saveUninitializedSession || request.session.isModified() diff --git a/lib/getCookieOpts.js b/lib/getCookieOpts.js new file mode 100644 index 0000000..ae199b8 --- /dev/null +++ b/lib/getCookieOpts.js @@ -0,0 +1,35 @@ +'use strict' + +const isConnectionSecure = require('./isConnectionSecure') + +module.exports = function getCookieOpts (cookieOpts, request) { + const originalMaxAge = cookieOpts.originalMaxAge || cookieOpts.maxAge || null + let secure = cookieOpts.secure || null + let sameSite = cookieOpts.sameSite || null + let expires = null + + if (originalMaxAge) { + expires = new Date(Date.now() + originalMaxAge) + } else if (cookieOpts.expires) { + expires = new Date(cookieOpts.expires) + } + + if (secure === 'auto') { + if (isConnectionSecure(request)) { + secure = true + } else { + sameSite = 'Lax' + secure = false + } + } + + return { + expires, + originalMaxAge, + sameSite, + secure, + path: cookieOpts.path || '/', + httpOnly: cookieOpts.httpOnly !== undefined ? cookieOpts.httpOnly : true, + domain: cookieOpts.domain || null + } +} diff --git a/lib/isConnectionSecure.js b/lib/isConnectionSecure.js new file mode 100644 index 0000000..4a3f6bf --- /dev/null +++ b/lib/isConnectionSecure.js @@ -0,0 +1,8 @@ +'use strict' + +module.exports = function isConnectionSecure (request) { + return ( + request.raw.socket?.encrypted === true || + request.headers['x-forwarded-proto'] === 'https' + ) +} diff --git a/lib/session.js b/lib/session.js index ab19bc8..da05050 100644 --- a/lib/session.js +++ b/lib/session.js @@ -2,7 +2,7 @@ const crypto = require('crypto') -const Cookie = require('./cookie') +const getCookieOpts = require('./getCookieOpts') const { configure: configureStringifier } = require('safe-stable-stringify') const stringify = configureStringifier({ bigint: false }) @@ -38,7 +38,7 @@ module.exports = class Session { prevSession[sessionIdKey] === sessionId && prevSession[encryptedSessionIdKey] ) || cookieSigner.sign(this.sessionId) - this.cookie = new Cookie(prevSession?.cookie || cookieOpts) + this.cookie = getCookieOpts(prevSession?.cookie || cookieOpts, request) if (prevSession) { // Copy over values from the previous session