Start learning free

LESSON 92 OF 173 · BACKEND: USERS AND SECURITY

Sessions with Cookies in TypeScript

Practice

A cookie is a small piece of data a site gives the browser with an answer. The browser keeps it and sends it back, on its own, with every later request to that site. That's how a website stays logged in without adding an Authorization header to each request.

The express-session package uses such a cookie to give each browser a session: an object the shop keeps for that browser, which every route finds in req.session. The cookie holds only the session's id, signed with a secret, so the browser can read the cookie but can't change it without the server noticing. You use the session like any object. In TypeScript, a declare module "express-session" line tells which properties a session may hold. For example, two routes could remember a shopper's favorite color:

declare module "express-session" { interface SessionData { color: string } }

app.post("/color", (req: Request, res: Response) => {
  req.session.color = req.body.color;
  res.json({ color: req.session.color });
});

app.get("/color", (req: Request, res: Response) => {
  res.json({ color: req.session.color || "blue" });
});

In this lesson, /login also puts the token in the session, and currentUser uses it when a request brings no Authorization header. When the header is there, it still wins. The tests use one client that keeps its cookies, like a browser:

GET /me  (no header, no cookie yet)  →  401  {"error": "Login required"}
POST /login  {"email": "ana@example.com", "password": "secret123"}  →  200  {"token": "…"}
GET /me  (no header)  →  200  {"email": "ana@example.com", "id": 2, "role": "customer"}
GET /welcome  (no header)  →  200  Welcome back, ana@example.com!
POST /products  {"name": "Desk", "price": 120}  (no header)  →  403  {"error": "Admins only"}
POST /login  {"email": "admin@example.com", "password": "admin-pass-123"}  →  200  {"token": "…"}
POST /products  {"name": "Desk", "price": 120}  (no header)  →  201  {"id": 9, "name": "Desk", "price": 120}
GET /me  (Bearer Ana's token)  →  200  {"email": "ana@example.com", "id": 2, "role": "customer"}
GET /me  (no header)  →  200  {"email": "admin@example.com", "id": 1, "role": "admin"}

Your task: turn sessions on with app.use(session({ ... })) and the secret "dev-secret-123", put the token in req.session.token at login, and let currentUser take the token from the session when the header gives none.


Assignment
Follow the Coding Tutorial to keep users logged in with a session and its signed cookie.


Hint
Without the header, header.replace("Bearer ", "") gives the empty text "": that's when to read req.session.token || "". The || "" matters for a request whose session has no token yet, and it keeps token a string. Declare token with let, since it may get a new value.


STEP 1 OF 4
    Ctrl + Enter to check

    Auth Sessions in TypeScript

    Keep going with TypeScript1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free