const crypto = require('crypto'); const { query } = require('../database/db'); /** * Hash an API key using SHA-256 */ function hashApiKey(key) { return crypto.createHash('sha256').update(key).digest('hex'); } /** * Generate a new API key with 'cpa_' prefix */ function generateApiKey() { const randomBytes = crypto.randomBytes(24); return 'cpa_' + randomBytes.toString('hex'); } /** * Middleware to validate API key from X-API-Key header */ async function validateApiKey(req, res, next) { const apiKey = req.headers['x-api-key']; if (!apiKey) { return res.status(401).json({ success: false, error: 'API key is required. Provide X-API-Key header.' }); } if (!apiKey.startsWith('cpa_')) { return res.status(401).json({ success: false, error: 'Invalid API key format' }); } try { const keyHash = hashApiKey(apiKey); const result = await query( `SELECT id, name, is_active, expires_at, rate_limit, allowed_ips FROM api_keys WHERE key_hash = $1`, [keyHash] ); const keyRecord = result.rows[0]; if (!keyRecord) { return res.status(401).json({ success: false, error: 'Invalid API key' }); } if (!keyRecord.is_active) { return res.status(401).json({ success: false, error: 'API key is inactive' }); } if (keyRecord.expires_at) { const expiryDate = new Date(keyRecord.expires_at); if (expiryDate < new Date()) { return res.status(401).json({ success: false, error: 'API key has expired' }); } } if (keyRecord.allowed_ips) { const allowedIps = keyRecord.allowed_ips.split(',').map(ip => ip.trim()); const clientIp = req.ip || req.connection.remoteAddress; if (!allowedIps.includes(clientIp)) { return res.status(403).json({ success: false, error: 'IP address not allowed for this API key' }); } } // Update last_used_at await query('UPDATE api_keys SET last_used_at = CURRENT_TIMESTAMP WHERE id = $1', [keyRecord.id]); req.apiKey = { id: keyRecord.id, name: keyRecord.name, rateLimit: keyRecord.rate_limit }; next(); } catch (error) { console.error('API key validation error:', error); return res.status(500).json({ success: false, error: 'Authentication error' }); } } module.exports = { validateApiKey, generateApiKey, hashApiKey };