import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'; /** * Optional API-key gate. When ALBION_API_KEY is set (required for any public * deployment), every /api route except health needs `Authorization: Bearer ` * or `?apiKey=`. When unset (localhost dev), the API is open. * * For real internet exposure, ALSO put this behind HTTPS + a private network * (Tailscale/WireGuard) — an API key alone is a minimum, not a full solution. */ export function registerAuth(app: FastifyInstance): void { const key = process.env.ALBION_API_KEY?.trim(); if (!key) { app.log.warn('ALBION_API_KEY not set — API is UNAUTHENTICATED (fine for localhost, unsafe if exposed).'); return; } app.addHook('onRequest', async (req: FastifyRequest, reply: FastifyReply) => { const url = req.url.split('?')[0]; // allow health checks and the static web UI without a key if (url === '/api/health' || !url.startsWith('/api/')) return; const header = req.headers.authorization; const bearer = header?.startsWith('Bearer ') ? header.slice(7).trim() : undefined; const queryKey = (req.query as { apiKey?: string })?.apiKey; const provided = bearer ?? queryKey; if (provided !== key) { return reply.code(401).send({ error: 'unauthorized — missing or invalid API key' }); } }); }