import { createUser, generateHash, updateSessionToken } from "./userHelper.js"; let db; let users; export function initAuth(app, db) { app.use(checkSessionToken); app.use('/admin', checkAuthorization('admin')); users = db.collection('users'); app.get('/auth', getUserInfo); app.post('/auth/login', loginUser); } async function getUserInfo(req, res) { // const sessiontoken = await updateSessionToken(users, req.user._id); // setTokenCookie(res, sessiontoken); res.status(200).send({ username: req.user.username, role: req.user.role, _id: req.user._id }); } async function checkSessionToken(req, res, next) { if (req.path.startsWith("/auth/")) { next(); return; } const token = req.cookies.jeopardytoken; let user = await users.findOne({sessiontoken: token}); if (user === null) { res.sendStatus(401); return; } req.user = { role: user.role, username: user.username, _id: user._id } next(); } function checkAuthorization(role) { return (req, res, next) => { if (req.user === undefined) { res.status(403).send(); return; } if (req.user.role === role) { next(); } else { res.status(403).send(); } } } async function loginUser(req, res) { const username = req.body.username; const password = req.body.password; let userCount = await users.estimatedDocumentCount(); let userobj = null; if (userCount <= 0) { // create first user userobj = await createUser(users, username, password, 'admin', true); } else { // authenticate user userobj = await authenticateUser(username, password); } if (userobj !== null) { setTokenCookie(res, userobj.sessiontoken); res.status(200).send({username: userobj.username, role: userobj.role, _id: userobj._id}); } else { res.sendStatus(403); } } export async function authenticateUser(username, password, updateSession = true) { let foundUser = await users.findOne({username}); if (foundUser === null) return null; const hash = generateHash(password, foundUser.salt, foundUser.iterations); if (hash === foundUser.hash) { if (updateSession) { let sessiontoken = await updateSessionToken(users, foundUser._id); return {sessiontoken, username, role: foundUser.role, _id: foundUser._id}; } else { return {sessiontoken: foundUser.sessiontoken, username, role: foundUser.role, _id: foundUser._id}; } } return null; } function setTokenCookie(res, sessiontoken) { const expires = new Date(); expires.setDate(expires.getDate() + 1); res.cookie('jeopardytoken', sessiontoken, { maxAge: 1e3 * 60 * 60 * 24 * 7, path: "/" }) }