/** * @cc-platform/server/auth — API key authentication middleware * * Extracted from the structurally identical auth code in both * remoteturtle/server/server.js and Inventory-Manager-CC/web/server/server.js. * * Usage: * const { createAuthMiddleware } = require('@cc-platform/server/auth'); * const auth = createAuthMiddleware(process.env.API_KEY); * app.use(auth.protectMutations); * * // Or protect specific routes: * app.post('/api/admin', auth.requireAuth, handler); */ 'use strict'; /** * Create an auth middleware suite for the given API key. * * If apiKey is falsy or empty, all requests are allowed through * (auth is effectively disabled). * * @param {string} apiKey - The expected API key (from env or config) * @returns {{ extractApiKey, requireAuth, protectMutations }} */ function createAuthMiddleware(apiKey) { /** * Extract an API key from a request. * Checks, in order: Authorization Bearer header, X-API-Key header, query param. */ function extractApiKey(req) { const auth = req.headers.authorization || ''; if (auth.startsWith('Bearer ')) return auth.slice(7); return req.headers['x-api-key'] || req.query.key || ''; } /** * Express middleware: require valid API key. * Passes through if auth is disabled (no API key configured). */ function requireAuth(req, res, next) { if (!apiKey) return next(); const token = extractApiKey(req); if (token === apiKey) return next(); return res.status(401).json({ error: 'Unauthorized — invalid or missing API key', }); } /** * Express middleware: protect non-GET methods. * GET, HEAD, and OPTIONS requests pass through without auth. * All other methods require a valid API key. */ function protectMutations(req, res, next) { if (['GET', 'HEAD', 'OPTIONS'].includes(req.method)) return next(); return requireAuth(req, res, next); } return { extractApiKey, requireAuth, protectMutations }; } module.exports = { createAuthMiddleware };