hectoday
DocsCoursesChangelog GitHub
DocsCoursesChangelog GitHub

Access Required

Enter your access code to view courses.

Invalid code

← All courses Authentication with @hectoday/http

What Is Authentication?

  • Who Are You?
  • HTTP Is Stateless
  • Project Setup

Passwords

  • Why Not Store Passwords Directly
  • Hashing with bcrypt
  • Building a Signup Route
  • Building a Login Route

Sessions and Cookies

  • What Is a Cookie?
  • What Is a Session?
  • Building Session Management
  • Protecting Routes
  • Logout
  • Cookie Security

Tokens

  • What Is a Token?
  • Anatomy of a JWT
  • Creating JWTs
  • Verifying JWTs
  • Sessions vs. Tokens

Putting It Together

  • Authorization
  • Common Mistakes
  • Capstone: User Management API

HTTP is stateless

In the last lesson, we saw that a server has no built-in way to know who is sending a request. All it gets is a bare HTTP message with no identity attached. But it actually gets worse than that, and understanding exactly how much worse is the whole point of this lesson. HTTP has a quirk that makes building “logged in” feel almost absurd when you first see it. The word you will hear over and over is stateless, and if it has never made sense to you, this is the lesson where it clicks.

What stateless actually means

When someone says HTTP is stateless, they mean something very specific: the server does not remember anything between requests. Period. Full stop.

Every time your browser sends a request to a server, the server treats it as if it has never seen you before. It does not know you were there five seconds ago. It does not know you are logged in. It does not know anything about any request that came before this one. Each request is a total stranger walking through the door.

This is not a bug. It is by design. HTTP was originally built for sharing documents on the early web. A browser requests a page, the server sends it back, and that is the end of the story. There is no ongoing relationship, no conversation, no memory. Just request, response, done.

Here is what it looks like from the server’s point of view:

Request 1: GET /about
  → Server returns the about page
  → Server immediately forgets this happened

Request 2: GET /pricing
  → Server returns the pricing page
  → Server has no idea this is the same person who just visited /about

Each request stands alone. The server processes it, sends a response, and moves on with its life. It keeps no record that ties request 1 to request 2. To the server, those two requests might as well have come from two different people on two different continents.

Why this is a nightmare for authentication

OK, let’s make it concrete. Think about what actually happens when you log in to a website:

  1. You type your email and password into a form.
  2. You click “Log in.” The browser sends your credentials to the server.
  3. The server checks them and confirms you are who you say you are.
  4. The server sends back “login successful.”
  5. You click a link to view your dashboard.
  6. The server receives a new request: GET /dashboard.

Here is the problem. At step 6, the server has no memory of step 3. It has no idea you just logged in. As far as this server is concerned, this GET /dashboard request could be from anyone in the world. Some anonymous visitor. A completely different user. A bot scraping the site. It does not matter that one second ago it just said “login successful” to your browser. That was a different request, and the server has already forgotten.

What do you think that means in practice? It means that without some way to carry identity across requests, you would have to send your email and password with every single request. Every page load. Every API call. Every image on the page. Every little fetch your app makes in the background. That is obviously impractical, wildly insecure, and nobody in their right mind would build it that way.

So the entire industry, over decades, has converged on exactly two solutions. You are going to build both in this course.

The two solutions

1. Server remembers you (sessions)

The first approach: make the server remember after all, just not for free.

After you log in, the server creates a small record in its own memory that basically says, “User 42 just logged in. I am going to give this login a random ID: abc123.” The server hands that random ID to your browser. Your browser stores it and sends it back with every future request. The server does not need to remember anything about you personally. It just needs to remember what abc123 means.

Login:
  Client → Server: "Here's my email and password"
  Server: "Checks out. I'll remember session abc123 = User 42"
  Server → Client: "Here, hold onto this: abc123"

Next request:
  Client → Server: "GET /dashboard, and by the way, here's abc123"
  Server: "abc123... that's User 42. Here's their dashboard."

The identity lives on the server. The client is just carrying a reference, like a coat-check ticket. The ticket itself means nothing. The server looks it up and figures out who the ticket belongs to.

2. Client carries the proof (tokens)

The second approach flips it around.

After you log in, the server creates a little signed document that says, “This is User 42, and this document is valid until tomorrow at noon.” It signs it so nobody can tamper with it, then hands it to your browser. Your browser sends that document back with every future request. The server does not need to remember anything. It just checks the signature to confirm the document is real, and then it trusts whatever the document says.

Login:
  Client → Server: "Here's my email and password"
  Server: "Checks out. Here's a signed document proving you're User 42"
  Server → Client: signed document

Next request:
  Client → Server: "GET /dashboard, and here's my signed document"
  Server: "Signature is valid, not expired. This is User 42. Here's their dashboard."

The identity lives on the client. The server just verifies it each time.

So which one do we use?

Short answer: both. And you will build both. Each approach has tradeoffs, and real production apps often mix them. Sessions are simpler and give you instant control (you can log someone out by deleting their session). Tokens are stateless on the server and work great for mobile apps and APIs where cookies are awkward. We will build sessions in Section 3 and tokens in Section 4, then compare them head to head.

But before we can do either one, there is something more fundamental we need to handle first: how do we safely deal with passwords in the first place? That is where Section 2 picks up.

For now, burn this into your head:

HTTP does not remember you, so we have to build that memory ourselves.

That one sentence is the reason sessions, cookies, tokens, JWTs, and basically the entire authentication world exists. The protocol forgets, so we have to remember.

In the next lesson, we stop talking theory and get our hands dirty. We will set up a real project, install Hectoday HTTP, and run a tiny server that actually responds to requests. From there, everything else builds on top.

After a user logs in and then requests GET /dashboard, what does the server know about this request by default (without any auth mechanism)?

What is the core difference between sessions and tokens?

← Who Are You? Project Setup →

© 2026 hectoday. All rights reserved.