Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Sessions and CSRF: keep identity on the server

Last updated: 5 Oct 20266 min read
tutorial
IntermediateBy AITrove Editorial

A session identifier is an opaque reference to server-side state. After authentication, a server can issue it in a cookie marked HttpOnly and Secure, with a SameSite policy suited to the flow. HttpOnly limits script access to the cookie; it does not stop the browser from sending the cookie with an eligible request. That automatic sending is why a state-changing endpoint needs a cross-site request forgery defense. A server-issued token bound to the active session can be checked on writes, alongside appropriate origin checks. SameSite is useful defense in depth, not a complete replacement for the write check. The model below generates unpredictable session and token values and compares the submitted token only after finding the session.

Case study

A reviewer is signed in and opens an inspection form. The server associates a fresh anti-forgery token with the session and includes it in that form. A write carrying the session cookie but no valid token is rejected before any record changes. Signing out invalidates the server-side session; merely deleting a browser display flag would not. In production, cookie scope, expiration, rotation, transport security, and login rate limits belong to the authentication design. This code demonstrates one boundary rather than a full login service.

Working contract

javascript
const { randomBytes, timingSafeEqual } = require("node:crypto");
const sessions = new Map();
const sessionId = randomBytes(24).toString("hex");
const writeToken = randomBytes(24).toString("hex");
sessions.set(sessionId, { reviewerId: 47, writeToken });
function mayWrite(cookieSessionId, submittedToken) {
  const session = sessions.get(cookieSessionId);
  if (!session || typeof submittedToken !== "string") return false;
  const expected = Buffer.from(session.writeToken, "hex");
  const supplied = Buffer.from(submittedToken, "hex");
  return expected.length === supplied.length && timingSafeEqual(expected, supplied);
}
console.log(mayWrite(sessionId, writeToken));
console.log(mayWrite(sessionId, "invalid"));

Observed output

Output
true
false

Cost and tradeoffs

Map lookup is expected O(1), while comparing fixed-size token buffers is O(K) for token byte length K. Keeping active sessions consumes O(S) memory or equivalent durable storage for S sessions. Random generation has a small fixed cost per session. A distributed service needs shared session state or a deliberate stateless design; copying a session map to every process would make sign-out inconsistent. Never log the raw cookie or token to troubleshoot failures. A forged request can arrive even when the user has not opened your form, so the server must own this check.

Common Mistakes

  • Do not keep bearer session identifiers in localStorage for convenience.
  • Do not treat SameSite alone as a complete write defense.
  • Do not compare a token before verifying its session exists.
  • Do not confuse a CSRF token with authorization to edit a particular record.

Continue through the stack

Form submission: validate on the server and return field errors; Browser storage: save convenience data without storing credentials; URLs and origins: separate location, query, and fragment.

Failure trace

A signed-in browser automatically attaches its session cookie to a forged write request initiated from another page. The server checks only that the cookie is valid and records the attacker's chosen note. Bind the mutation to a CSRF defense suited to the session design, check the request's intended origin where appropriate, and keep the session reference out of script-readable storage when possible.

Verification

  • Submit an authenticated write without the expected CSRF proof and confirm rejection.
  • Try the same request with a valid proof and verify the stored result and response status.
  • Sign out, replay the old cookie, and confirm the server no longer recognizes that session.

Decision note

Cookie flags narrow exposure but do not replace a complete write defense. Session validation, request intent, and record-level permission are separate checks that all matter before storage changes.

Advanced connections

Password Verification and Login Budgets; Account Recovery and Session Revocation; Federated Login Callback Boundary.

Runtime connections

PHP Session Rotation, Locking, and Logout.

web-tech
web-development
Storage details