// API Key Authentication Middleware import crypto from 'crypto' import { logit, logerror } from './logit.js' // API Keys aus Umgebungsvariablen oder Datenbank laden const API_KEYS = new Set( (process.env.API_KEYS || '').split(',') .map(key => key.trim()) .filter(key => key.length > 0) ) // Optionaler Modus: wenn keine API_KEYS definiert sind, wird keine Auth durchgeführt const AUTH_REQUIRED = (process.env.API_AUTH_REQUIRED || '').trim().toLowerCase() === 'true' // Log authentication status on startup if (AUTH_REQUIRED || API_KEYS.size > 0) { logit(`API Authentication: ENABLED (${API_KEYS.size} keys configured)`) } else { logit(`API Authentication: DISABLED`) } /** * Generate a new API key (for administrative purposes) * @returns {string} - New API key */ export const generateApiKey = () => { return crypto.randomBytes(32).toString('hex') } /** * Middleware to validate API key * Accepts API key in: * - Header: X-API-Key * - Query parameter: apikey */ export const validateApiKey = (req, res, next) => { // Skip auth if not required if (!AUTH_REQUIRED && API_KEYS.size === 0) { return next() } // Extract API key from header or query parameter const apiKey = req.header('X-API-Key') || req.query.apikey if (!apiKey) { logit(`ERROR API Auth: No API key provided - ${req.ip}`) return res.status(401).json({ err: 'UNAUTHORIZED', message: 'API key required. Provide X-API-Key header or apikey query parameter.' }) } // Validate API key if (!API_KEYS.has(apiKey)) { logit(`ERROR API Auth: Invalid API key - ${req.ip}`) return res.status(403).json({ err: 'FORBIDDEN', message: 'Invalid API key' }) } // Log successful authentication logit(`API Auth: Valid request from ${req.ip}`) // API key is valid, proceed next() } /** * Add API key to the allowed list (for runtime management) * @param {string} apiKey - API key to add */ export const addApiKey = (apiKey) => { API_KEYS.add(apiKey) logit(`API Key added: ${apiKey.substring(0, 8)}...`) } /** * Remove API key from the allowed list * @param {string} apiKey - API key to remove */ export const removeApiKey = (apiKey) => { API_KEYS.delete(apiKey) logit(`API Key removed: ${apiKey.substring(0, 8)}...`) } /** * Check if API authentication is active * @returns {boolean} */ export const isAuthActive = () => { return AUTH_REQUIRED || API_KEYS.size > 0 }