- New database/auth.js: shared server-side GM check using session store - database/server.js: crypto-random session generation, server-side session storage, GM auth from session instead of x-gm-secret header - database/routes/playerRoutes.js: GM-only endpoints use server-side auth - database/routes/sessionRoutes.js: session creation/lookup endpoints - database/routes/bestiaryRoutes.js: GM auth from server-side session - database/routes/rulesRoutes.js: GM auth from server-side session - src/App.js: send x-session-id header with API requests - src/components/BestiaryTab.jsx: use session-based GM auth
34 lines
1.0 KiB
JavaScript
34 lines
1.0 KiB
JavaScript
// Shared GM authorization middleware
|
|
// Authorizes based on server-side session lookup via x-session-id header.
|
|
// Does NOT trust x-gm-secret header (that was the vulnerability).
|
|
//
|
|
// Usage in async route handlers:
|
|
// const { requireGM } = require('../auth');
|
|
// if (!(await requireGM(req, res))) return;
|
|
//
|
|
// Usage in sync middleware (not supported — this is async only).
|
|
|
|
const { validateSession } = require('./sessionModel');
|
|
|
|
async function requireGM(req, res) {
|
|
const sessionId = req.headers['x-session-id'];
|
|
if (!sessionId) {
|
|
res.status(401).json({ error: 'Authentication required' });
|
|
return false;
|
|
}
|
|
|
|
const session = await validateSession(sessionId);
|
|
if (!session || !session.data || !session.data.playerName) {
|
|
res.status(401).json({ error: 'Invalid or expired session' });
|
|
return false;
|
|
}
|
|
|
|
if (session.data.playerName.toLowerCase() !== 'gm') {
|
|
res.status(403).json({ error: 'GM access required' });
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
module.exports = { requireGM }; |