← back to AbramsOS

middleware/auth.js

37 lines

const auth = require('../lib/auth');

// Hydrate req.session + req.userId from the cookie
async function loadSessionMiddleware(req, _res, next) {
  const sid = req.cookies?.[auth.SESSION_COOKIE] || req.signedCookies?.[auth.SESSION_COOKIE];
  if (!sid) { if (process.env.SINGLE_USER_AUTOLOGIN) req.userId = process.env.SINGLE_USER_AUTOLOGIN; return next(); }
  const session = await auth.loadSession(sid);
  if (!session) { if (process.env.SINGLE_USER_AUTOLOGIN) req.userId = process.env.SINGLE_USER_AUTOLOGIN; return next(); }
  req.session = session;
  req.userId = session.user_id;
  next();
}

// Reject unauthenticated requests; redirect HTML to /signin, JSON gets 401.
// FLEET BASIC-AUTH MODE: when SINGLE_USER_AUTOLOGIN is set, the app is deployed behind
// nginx HTTP Basic Auth (admin/DW2024!) — the door is already guarded, so trust the
// request and act as the single owner instead of showing the app's own email/TOTP login.
function requireAuth(req, res, next) {
  if (req.userId) return next();
  if (process.env.SINGLE_USER_AUTOLOGIN) { req.userId = process.env.SINGLE_USER_AUTOLOGIN; return next(); }
  if (req.accepts('html')) return res.redirect('/signin?next=' + encodeURIComponent(req.originalUrl));
  return res.status(401).json({ error: 'unauthenticated' });
}

// Require recent (within 60s) successful TOTP verify
function requireStepUp(req, res, next) {
  if (!req.userId) {
    if (req.accepts('html')) return res.redirect('/signin?next=' + encodeURIComponent(req.originalUrl));
    return res.status(401).json({ error: 'unauthenticated' });
  }
  if (auth.isStepUpValid(req.session)) return next();
  if (req.accepts('html')) return res.redirect('/step-up?next=' + encodeURIComponent(req.originalUrl));
  return res.status(403).json({ error: 'step_up_required' });
}

module.exports = { loadSessionMiddleware, requireAuth, requireStepUp };