Interview Q&A / Node.js

IntermediateQuick answer1 min readUpdated 3 Oct 2026

Where should a browser app store a JWT: localStorage or an httpOnly cookie?

SHORT ANSWER

An httpOnly, Secure, SameSite cookie keeps the token out of reach of JavaScript, so an XSS bug cannot steal it, but you must then handle CSRF. localStorage is simple but readable by any script on the page.

Explain it simply

Where you keep your house key matters. localStorage is like a key in a box on the porch: easy to reach for you, and also easy for anyone who gets onto the porch. If an attacker injects a script into your page (XSS), that script can read localStorage and send your token away.

An httpOnly cookie is a key held by the guard: the browser attaches it automatically to requests, but page JavaScript cannot read it.

Example

js
app.post("/login", async (req, res) => {
  const user = await verifyCredentials(req.body);
  const token = jwt.sign({ sub: user.id }, process.env.JWT_SECRET, { expiresIn: "15m" });

  res.cookie("access_token", token, {
    httpOnly: true,          // not readable from document.cookie
    secure: true,            // HTTPS only
    sameSite: "lax",         // limits cross-site sending (CSRF)
    maxAge: 15 * 60 * 1000,
  });
  res.sendStatus(204);
});

Trade-offs:

localStoragehttpOnly cookie
Stolen by XSSyesno (but attacker can still make requests from the page)
CSRF risknone, you attach it manuallyyes, mitigate with SameSite and CSRF tokens
Works across domainseasy, via headerneeds CORS credentials

Whichever you pick, fix XSS first, use short expiries and HTTPS.

What to say in the interview

"For a browser app I prefer an httpOnly, Secure, SameSite cookie because scripts cannot read it. That moves the risk to CSRF, which SameSite and CSRF tokens cover. localStorage is easier but exposes the token to XSS."

Common mistakes

  • Putting long-lived tokens in localStorage.
  • Forgetting secure: true, so the cookie travels over plain HTTP.

#auth#jwt#security

Related questions

Practise more Node.js questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open Node.js quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.