Every page for logged-in users starts the same way: find the user from the token, and answer 401 when there is none. Copying those lines into every route works until the day you forget them on one route, and that route is open to everybody. A middleware writes the check once, and one word puts it in front of any route.
A middleware is a function that Express runs before a route's function. It takes three parameters: req: Request and res: Response, like a route, and next: NextFunction, the function it calls to let the request go on. You already use one: express.json(), which reads the body of every request. Here is a small one that has nothing to do with logins: it prints the path of each request before the route runs.
function logCalls(req: Request, res: Response, next: NextFunction) {
console.log("calling", req.path);
next();
}
app.get("/hello", logCalls, (req: Request, res: Response) => {
res.send("Hello!");
});
A middleware either answers the request itself, and then the route's function never runs, or it calls next(). If it does neither, the request never gets an answer. The middleware and the route receive the same req object, so what the middleware stores on it, like req.user, the route can read. Express's Request type has no user property: the declare global line at the top of the code adds user: UserInfo to it.
Ana (id 1) signs up and logs in first; <token> is the token that login answered:
POST /register {"email": "ana@example.com", "password": "secret123"} → 201 {"email": "ana@example.com", "id": 1}
POST /login {"email": "ana@example.com", "password": "secret123"} → 200 {"token": "<token>"}
GET /me Authorization: Bearer <token> → 200 {"email": "ana@example.com", "id": 1}
GET /me (no header) → 401 {"error": "Login required"}
GET /welcome Authorization: Bearer <token> → 200 Welcome back, ana@example.com!
GET /welcome (no header) → 401 {"error": "Login required"}
GET /welcome Authorization: Bearer 0123456789abcdef0123456789abcdef → 401 {"error": "Login required"}
Your task: below currentUser, write the middleware loginRequired: it answers 401 "Login required" when currentUser(req) finds nobody, and otherwise stores the user in req.user and calls next(). Put it on /me, whose function now just answers req.user, and add a protected GET /welcome that answers the text Welcome back, <email>!.
Assignment
Follow the Coding Tutorial to write the loginRequired middleware and protect /me and /welcome with it.
Hint
Write loginRequired between the path and the route's function, just its name, without parentheses: Express calls it. Don't forget next() at the end of the middleware, or the request never reaches the route.
Free plan: 30 tutor messages. PRO is unlimited.
