Learn / Frameworks / Express / Sessions, Cookies and CSRF

Express · Lesson 7 of 15

Sessions, Cookies and CSRF

Server-side sessions vs JWT, cookie flags and CSRF for cookie-based auth.

  • Intermediate
  • 16 min read
  • 3 objectives

Before this lessonLesson 6: Async Errors and Central Handlers

What you will learn

  • Store a session
  • Set cookie flags
  • Protect a state-changing route

Your Progress

0 of 15 lessons 0%

  • Lessons0 / 15
  • Completed0
  • Est. time left~ 4 hours

Create a free account to keep your progress on every device.

JWTs are convenient for APIs. Browser apps often do better with a server-side session in a cookie: you can revoke it, and you do not store secrets in localStorage.

express-session

import session from "express-session";
import pgSimple from "connect-pg-simple";

const PgStore = pgSimple(session);
app.set("trust proxy", 1);
app.use(session({
  store: new PgStore({ pool, tableName: "session" }),
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: { httpOnly: true, secure: true, sameSite: "lax", maxAge: 7 * 24 * 3600 * 1000 },
}));

app.post("/login", wrap(async (req, res) => {
  const user = await verify(req.body);
  req.session.userId = user.id;
  res.json({ ok: true });
}));

CSRF for cookie auth

A cookie is sent automatically. A malicious site can POST to your API unless you require a CSRF token (double-submit cookie, or SameSite=strict plus a custom header).

app.use((req, res, next) => {
  if (["GET", "HEAD", "OPTIONS"].includes(req.method)) return next();
  if (req.get("X-Requested-With") !== "XMLHttpRequest") {
    return res.status(403).json({ error: "CSRF" });
  }
  next();
});
Up next · Lesson 8File Uploads with MulterAccept multipart files, cap size and write to disk or S3.