WTF Sessions
What is the deal with sessions? Why are sessions important to me? How do I implement them?
The deal with sessions
The web is a stateless protocol. If we navigate to a new page, or even refreshing the same page, the defautl browser semantics do not persist state. Sessions are a way to track interactions across page loads. Said another way Hyper Text Transfer Protocol (HTTP) does know what a user agent is doing between page loads. This becomes a problem if we do need to keep track of state navigating between pages. The classic example is a shopping cart. But session is also massively imporant to understand how auth security works.
Why sessions are important
In the past decade or so many developers onboarded to web dev by learning about single page applications which often skip session state concerns. After all, if you aren't navigating, you don't really need to know or care about session, right? Unfortunately, as we've all felt, this leads to a poor end user experience. When a page reload happens on purpose (or accident) state is lost. Sometimes it is just a simple thing like a particular selected item in a list. Sometimes its an entire form of details I did not want to have to retype again. Sessions are a crucial primitive for creating bulletproof web consumer experiences that prevents these sorts of poor user experiences.
Implementing a session
Most web server runtime environments will have a session
primitive built-in but to help you understand what they are we'll implement sessions completely from scratch.
We need a way to track user interactions between page reloads. There are a few ways to do this but most web apps use HTTP cookies. One big reason is that cookies are read only from clientside JavaScript which means third party code cannot tamper with state.
console.log(document.cookie)
// logs "session_cookie=xxx"
document.cookie = "session_cookie=yyy"
console.log(document.cookie)
// logs "session_cookie=xxx"
At the lowest level, cookies are created, and updated, with the set-cookie
header.
Set-Cookie: session_cookie=xxx; HttpOnly
Cookies are deleted by setting the expired property.
Set-Cookie: session_cookie=xxx; Expires=1 Jan 2020 01:00:00 GMT; HttpOnly
When a new request is made, the browser sends previously stored cookies for the current domain back to the server with the Cookie
header:
GET /index.html HTTP/2.0
Host: www.example.com
Cookie: session_cookie=xxx
HTTPonly cookies are an elegent solution for implementing session but only half the solution. We still need to consider how we're going to persist state on the backend.
Saving session state
Typically, sessions are either durably persisted in a backend database and the cookie is used to look the values up, or encoded directly into the cookie state. One isn't explicitly better than the other but both techniques have tradeoffs. Database backed sessions can be as large as you want but of course then require talking to a database which can introduce latency. Sessions saved in cookie state can only be 4KB but will need to be crypographically verified and somewhat frequently expired/refreshed. Again, these are just tradeoffs, and generally I think its probably easiest to start with stateless sessions and grow into database backed sessions if the application needs grow complex enough to justify it. A good framework will make it pretty straightforward to switch. (It is very easy to upgrade with OpenJS Architect.)
Implementing `Session` with node.js
Ok lets build a counter example! The end result is a page that tracks a counter across page refreshes.