import crypto from 'crypto'; import config from '../config/config.js'; const TOKEN_SECRET = process.env.ADMIN_SECRET || config.ADMIN_IDS[0] || 'change-me'; const COOKIE_NAME = 'admin_token'; const MAX_AGE = 24 * 60 * 60 * 1000; function signToken(data) { const payload = JSON.stringify({ ...data, exp: Date.now() + MAX_AGE }); const b64 = Buffer.from(payload).toString('base64'); const sig = crypto.createHmac('sha256', TOKEN_SECRET).update(b64).digest('hex'); return `${b64}.${sig}`; } function verifyToken(token) { try { const [b64, sig] = token.split('.'); const expected = crypto.createHmac('sha256', TOKEN_SECRET).update(b64).digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) return null; const payload = JSON.parse(Buffer.from(b64, 'base64').toString()); if (payload.exp < Date.now()) return null; return payload; } catch { return null; } } export function requireAuth(req, res, next) { const token = req.cookies?.[COOKIE_NAME]; if (!token) return res.redirect('/login'); const payload = verifyToken(token); if (!payload) { res.clearCookie(COOKIE_NAME); return res.redirect('/login'); } req.admin = payload; next(); } export function handleLogin(req, res) { const { token } = req.body || {}; if (token !== TOKEN_SECRET) { return res.status(401).send(renderLogin('Invalid token')); } const signed = signToken({ role: 'admin' }); res.cookie(COOKIE_NAME, signed, { httpOnly: true, sameSite: 'strict', maxAge: MAX_AGE, secure: false }); res.redirect('/'); } export function handleLogout(req, res) { res.clearCookie(COOKIE_NAME); res.redirect('/login'); } function renderLogin(error) { return `
${error}
` : ''}