HTTP forgets. Two requests from the same browser arrive at your Express 24,430 app as unrelated events, and nothing in the protocol links them. Every login is a workaround: the server hands the client a small piece of state, the client sends it back, and the server decides what it means.
That state comes in two shapes, and the difference is the whole of this section. An opaque identifier — a session ID in a cookie — means nothing on its own; the server looks it up in a store. A self-contained token — a signed JWT — carries its claims inside, so the server needs no lookup but cannot easily take the token back. Sessions trade a lookup for instant revocation; tokens trade revocation for statelessness. A server-rendered app on one origin is happiest with sessions; a React 7,897 front end plus a mobile client usually prefers tokens.
Everything here rests on primitives from Cryptography — HMAC signing, random identifiers, password hashing, the anatomy of a JWT. This section wires them into a request pipeline and shows what a rejection looks like.
