Security fix: GM authorized from server-side session via x-session-id header
- 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
This commit is contained in:
34
database/auth.js
Normal file
34
database/auth.js
Normal file
@@ -0,0 +1,34 @@
|
||||
// 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 };
|
||||
Reference in New Issue
Block a user