Part of #7. Cookie-based auth via client-sessions (encrypted, signed cookie — no server-side store), living in the api express() app. Protect page routes with an array-of-paths guard rather than per-route checks (Express Core).
Sessions (in src/api/index.js)
import express from "express";
import nocache from "nocache";
import sessions from "client-sessions";
const server = express();
export default server;
server.use(sessions({
cookieName: "session",
secret: process.env.SESSION_SECRET, // required, dev + prod
duration: 24 * 60 * 60 * 1000, // 24h
activeDuration: 5 * 60 * 1000, // sliding 5m
cookie: { httpOnly: true, secure: true, sameSite: "lax" },
}));
server.post("/api/login", express.json(), (req, res) => {
// validate credentials →
req.session.user = { id, name };
res.json({ ok: true });
});
server.post("/api/logout", (req, res) => { req.session.reset(); res.json({ ok: true }); });
Protect routes — array of paths + nocache() + guard
server.use(["/budget", "/goals", "/settings"], nocache(), signinRequired);
function signinRequired(req, res, next) {
if (!req.session?.user) return res.status(401).json({ error: "unauthorized" });
next();
}
Notes
client-sessions is stateless — no store to configure, but the cookie is size-limited (~4KB); keep session payloads small.
SESSION_SECRET must be set in dev (.env) and prod.
Tasks
Acceptance
- Login sets an encrypted session cookie;
signinRequired blocks unauthenticated requests (401) on protected paths; logout resets the session. Identical in dev and prod.
Part of #7. Cookie-based auth via
client-sessions(encrypted, signed cookie — no server-side store), living in theapiexpress()app. Protect page routes with an array-of-paths guard rather than per-route checks (Express Core).Sessions (in
src/api/index.js)Protect routes — array of paths +
nocache()+ guardNotes
client-sessionsis stateless — no store to configure, but the cookie is size-limited (~4KB); keep session payloads small.SESSION_SECRETmust be set in dev (.env) and prod.Tasks
client-sessions+nocachedepssessions(...)insrc/api/index.js/api/login+/api/logoutsigninRequiredguard mounted across the protected-paths arraySESSION_SECRETAcceptance
signinRequiredblocks unauthenticated requests (401) on protected paths; logout resets the session. Identical in dev and prod.