/** * GoldRate Engine — API Key Authentication Middleware * * Validates API keys against Supabase api_keys table. * Keys have 30-day expiry and are tied to a price source (SLN or IBJA). * * Pass your key as: * Header: x-api-key: your_key * OR Query: ?apikey=your_key * * After auth, req.priceSource is set to 'SLN' or 'IBJA' */ const { getIsConnected, getClient } = require('./db'); // In-memory cache for validated keys (avoid DB hit every request) const keyCache = new Map(); const KEY_CACHE_TTL = 5 * 60 * 1000; // 5 minutes function authMiddleware(req, res, next) { const apiKey = req.headers['x-api-key'] || req.query.apikey; if (!apiKey) { return res.status(401).json({ success: false, error: 'API key required. Pass it as header "x-api-key" or query "?apikey=YOUR_KEY"' }); } // Master key from .env (never expires, for admin/frontend use) if (apiKey === process.env.API_KEY) { req.priceSource = 'SLN'; // Default to SLN for master key req.isMasterKey = true; return next(); } // Check key cache first const cached = keyCache.get(apiKey); if (cached && (Date.now() - cached.cachedAt) < KEY_CACHE_TTL) { const now = new Date(); if (!cached.is_active) { return res.status(403).json({ success: false, error: 'API key has been deactivated. Contact us to get a new key.', contact: process.env.CONTACT_PHONE || '9360345770' }); } if (new Date(cached.expires_at) < now) { return res.status(403).json({ success: false, error: 'API key expired. Contact us to renew.', contact: process.env.CONTACT_PHONE || '9360345770' }); } req.priceSource = cached.source; req.keyOwner = cached.owner_name; return next(); } // Look up in Supabase if (!getIsConnected()) { // If DB not connected, reject non-master keys return res.status(403).json({ success: false, error: 'Invalid API key' }); } const supabase = getClient(); supabase .from('api_keys') .select('*') .eq('api_key', apiKey) .single() .then(({ data, error }) => { if (error || !data) { return res.status(403).json({ success: false, error: 'Invalid API key. Contact us to get one.', contact: process.env.CONTACT_PHONE || '9360345770' }); } // Cache the key data keyCache.set(apiKey, { ...data, cachedAt: Date.now() }); // Check if active if (!data.is_active) { return res.status(403).json({ success: false, error: 'API key has been deactivated. Contact us to get a new key.', contact: process.env.CONTACT_PHONE || '9360345770' }); } // Check expiry const now = new Date(); if (new Date(data.expires_at) < now) { return res.status(403).json({ success: false, error: 'API key expired. Contact us to renew.', expired_at: data.expires_at, contact: process.env.CONTACT_PHONE || '9360345770' }); } // Valid key — set source req.priceSource = data.source; // 'SLN' or 'IBJA' req.keyOwner = data.owner_name; next(); }) .catch(() => { return res.status(500).json({ success: false, error: 'Authentication service error. Please try again.' }); }); } module.exports = { authMiddleware };