conduit-full — auth & request flow

One middleware, two behaviors: missing auth isn't rejected, it's just anonymous.

verifyToken runs in front of nearly every route, but it's not a gate — no Authorization header just means the request proceeds with req.loggedUser left unset. Each controller decides for itself whether that's acceptable. See System Architecture for where this sits in the request chain.

Token Issuance

POST /api/users/login { email, password }
↓ bcryptCompare → jwtSign (7-day expiry, HS256 only)
{ user: { …, token } }
↓ stored client-side, replayed as Authorization: Token <jwt>
verifyToken middleware, every subsequent request

What verifyToken Actually Does

no header next() immediately — request continues anonymous, no error
valid token req.loggedUser set from the verified email, request continues
malformed / invalid throws, caught by errorHandler, request stops

Two Endpoints, Same Middleware, Different Contract

Soft auth

GET /api/articles/:slug

Works with or without a token. If one's present, the response's favorited/following fields reflect the real logged-in user's state; if not, they're just false. No UnauthorizedError either way.

Hard auth

POST /api/articles

Same middleware, but the controller itself checks if (!loggedUser) throw new UnauthorizedError() as its first line — the gate is in application code, not the middleware.

!

This exact distinction is what the frontend's getComments.ts got wrong: the GET-comments route is soft-auth, so whether a token is sent genuinely changes each comment author's following/followersCount — but the service never accepted a headers param at all, unlike its siblings. Comments were always fetched as if anonymous, even when logged in. Fixed in the service; see todo.md Phase 58 for the full trace.