From 3c41b40c5fffcc3de2d2a26498c1990bd6a24979 Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Mon, 18 Aug 2025 20:43:28 +0200 Subject: [PATCH] refactor: create fast tracks for cookie parsing --- apps/server/src/middleware/authenticate.ts | 35 ++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/apps/server/src/middleware/authenticate.ts b/apps/server/src/middleware/authenticate.ts index ac0535230..3b6c77b92 100644 --- a/apps/server/src/middleware/authenticate.ts +++ b/apps/server/src/middleware/authenticate.ts @@ -1,5 +1,3 @@ -import { LogOrigin } from 'ontime-types'; - import express, { type Request, type Response, type NextFunction } from 'express'; import type { IncomingMessage } from 'node:http'; import type { WebSocket } from 'ws'; @@ -7,7 +5,6 @@ import { parse as parseCookie } from 'cookie'; import { hashPassword } from '../utils/hash.js'; import { srcFiles } from '../setup/index.js'; -import { logger } from '../classes/Logger.js'; import { hashedPassword, hasPassword } from '../api-data/session/session.service.js'; import { noopMiddleware } from './noop.js'; @@ -53,6 +50,9 @@ export function makeAuthenticateMiddleware(prefix: string) { return { authenticate: noopMiddleware, authenticateAndRedirect: noopMiddleware }; } + // pre-compute the login redirect base URL to avoid string concatenation on every request + const loginRedirectBase = `${prefix}/login?redirect=`; + function authenticate(req: Request, res: Response, next: NextFunction) { if (req.query.token) { if (req.query.token === hashedPassword) { @@ -98,7 +98,7 @@ export function makeAuthenticateMiddleware(prefix: string) { return next(); } - res.redirect(`${prefix}/login?redirect=${req.originalUrl}`); + res.redirect(loginRedirectBase + req.originalUrl); } return { authenticate, authenticateAndRedirect }; @@ -124,14 +124,23 @@ export function authenticateSocket(_ws: WebSocket, req: IncomingMessage, next: ( } } - // check if token is in the params - const url = new URL(req.url || '', `http://${req.headers.host}`); - const token = url.searchParams.get('token'); - if (token === hashedPassword) { + // check if token is in the params - simple string check first + const urlString = req.url || ''; + if (urlString.includes(`token=${hashedPassword}`)) { return next(); } - logger.warning(LogOrigin.Client, 'Unauthorized WebSocket connection attempt'); + // fallback to full URL parsing for other formats + try { + const url = new URL(urlString, `http://${req.headers.host}`); + const token = url.searchParams.get('token'); + if (token === hashedPassword) { + return next(); + } + } catch (_) { + // ignore URL parsing errors + } + return next(new Error('Unauthorized')); } @@ -153,6 +162,14 @@ function setSessionCookie(res: Response, token: string) { * And want to extract its value */ function getTokenFromCookie(cookieContents: string): string | undefined { + // Fast path: check if the hashed password is directly in the cookie string + // This avoids JSON parsing for the common case + const cookieTokenString = '"token":"' + hashedPassword + '}"'; + if (cookieTokenString && cookieContents.includes(cookieTokenString)) { + return hashedPassword; + } + + // Fallback to JSON parsing for other cases or validation try { const cookie = JSON.parse(cookieContents); if (cookie && typeof cookie.token === 'string') {