← back to NationalPaperHangers
lib/booking-token.js
34 lines
// HMAC-signed booking-view token. Embedded in confirmation-email URLs so that
// the booking detail page (/bookings/:uuid?t=...) cannot be enumerated by
// guessing UUIDs. The signing key is BOOKING_SIGNING_SECRET, falling back to
// SESSION_SECRET (which throws in production if unset).
const crypto = require('crypto');
function getKey() {
const k = process.env.BOOKING_SIGNING_SECRET || process.env.SESSION_SECRET;
if (!k || k === 'dev-secret-change-me') {
if (process.env.NODE_ENV === 'production') {
throw new Error('BOOKING_SIGNING_SECRET (or SESSION_SECRET) must be set in production');
}
}
return k || 'dev-only-not-for-prod';
}
function sign(uuid) {
return crypto.createHmac('sha256', getKey()).update(String(uuid)).digest('base64url').slice(0, 24);
}
function verify(uuid, supplied) {
if (!uuid || !supplied) return false;
const expected = sign(uuid);
if (expected.length !== supplied.length) return false;
try {
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(supplied));
} catch {
return false;
}
}
module.exports = { sign, verify };