fix: add token query parameter support to auth middleware for web mode image loading

The /api/fs/image endpoint requires authentication, but when loading images via
CSS background-image or img tags, only query parameters can be used (headers
cannot be set). Web mode passes the session token as a query parameter (?token=...),
but the auth middleware didn't recognize it, causing image requests to fail.

This fix adds support for the 'token' query parameter in the checkAuthentication
function, allowing the auth middleware to validate web mode session tokens when
they're passed as query parameters.

Now image loads work correctly in web mode by:
1. Client passes session token in URL: ?token={sessionToken}
2. Auth middleware recognizes and validates the token query parameter
3. Image endpoint successfully serves the image after authentication

This fixes the issue where kanban board background images were not visible
in web mode.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
DhanushSantosh
2026-01-18 21:23:18 +05:30
parent dd26de9f55
commit 749fb3a5c1
2 changed files with 13 additions and 51 deletions

View File

@@ -320,6 +320,15 @@ function checkAuthentication(
return { authenticated: false, errorType: 'invalid_api_key' };
}
// Check for session token in query parameter (web mode - needed for image loads)
const queryToken = query.token;
if (queryToken) {
if (validateSession(queryToken)) {
return { authenticated: true };
}
return { authenticated: false, errorType: 'invalid_session' };
}
// Check for session cookie (web mode)
const sessionToken = cookies[SESSION_COOKIE_NAME];
if (sessionToken && validateSession(sessionToken)) {
@@ -335,8 +344,9 @@ function checkAuthentication(
* Accepts either:
* 1. X-API-Key header (for Electron mode)
* 2. X-Session-Token header (for web mode with explicit token)
* 3. apiKey query parameter (fallback for cases where headers can't be set)
* 4. Session cookie (for web mode)
* 3. apiKey query parameter (fallback for Electron, cases where headers can't be set)
* 4. token query parameter (fallback for web mode, needed for image loads via CSS/img tags)
* 5. Session cookie (for web mode)
*/
export function authMiddleware(req: Request, res: Response, next: NextFunction): void {
const result = checkAuthentication(

View File

@@ -1,7 +1,7 @@
/**
* GET /image endpoint - Serve image files
*
* Requires authentication via:
* Requires authentication via auth middleware:
* - apiKey query parameter (Electron mode)
* - token query parameter (web mode)
* - session cookie (web mode)
@@ -13,21 +13,11 @@ import type { Request, Response } from 'express';
import * as secureFs from '../../../lib/secure-fs.js';
import path from 'path';
import { PathNotAllowedError } from '@automaker/platform';
import { validateApiKey, validateSession } from '../../../lib/auth.js';
import { getErrorMessage, logError } from '../common.js';
const SESSION_COOKIE_NAME = 'automaker_session';
export function createImageHandler() {
return async (req: Request, res: Response): Promise<void> => {
try {
// Authenticate the request
const isAuthenticated = checkImageAuthentication(req);
if (!isAuthenticated) {
res.status(401).json({ success: false, error: 'Authentication required' });
return;
}
const { path: imagePath, projectPath } = req.query as {
path?: string;
projectPath?: string;
@@ -81,41 +71,3 @@ export function createImageHandler() {
}
};
}
/**
* Check if image request is authenticated
* Supports multiple authentication methods
*/
function checkImageAuthentication(req: Request): boolean {
// Check for API key in header (Electron mode)
const headerKey = req.get('x-api-key');
if (headerKey && validateApiKey(headerKey)) {
return true;
}
// Check for session token in header (web mode)
const sessionTokenHeader = req.get('x-session-token');
if (sessionTokenHeader && validateSession(sessionTokenHeader)) {
return true;
}
// Check for API key in query parameter (fallback)
const queryKey = req.query.apiKey as string | undefined;
if (queryKey && validateApiKey(queryKey)) {
return true;
}
// Check for session token in query parameter (web mode with token)
const queryToken = req.query.token as string | undefined;
if (queryToken && validateSession(queryToken)) {
return true;
}
// Check for session cookie (web mode)
const sessionCookie = req.cookies?.[SESSION_COOKIE_NAME];
if (sessionCookie && validateSession(sessionCookie)) {
return true;
}
return false;
}