DevPath · Learn to code ESPTEN

End-to-end authentication

The full flow: from login to the protected route

The end-to-end journey

[Front] login(user, password)
   │  POST /login  { user, password }
   ▼
[Back] validates credentials ──> issues signed token (with exp)
   │  200  { token }
   ▼
[Front] stores the token and attaches it on every request:
   │  GET /profile   Authorization: Bearer <token>
   ▼
[Back] verifies the token ──> knows who you are ──> responds

Step by step

  1. Login: the user sends user and password. The backend checks the password (against the stored hash, never against the plaintext password).
  2. Issuance: if correct, the backend issues a credential: a signed token (JWT) or a session id. It includes an expiry (exp).
  3. Stored in the front: the frontend stores the credential (cookie or localStorage).
  4. Attach: on every later request the front sends the credential. With JWT, in the Authorization: Bearer <token> header.
  5. Verification: the backend reads the header, verifies the signature and the expiry, and loads the user (e.g. into req.user).
  6. Protected routes: a middleware blocks the way with 401 if there's no valid credential, before reaching the handler.

Expiration and refresh tokens

An access token must last little (minutes): if it's stolen, the damage expires soon. But asking the user to log in again every 15 minutes is horrible. Solution: two tokens.

This way you combine security (small theft window) and convenience (long sessions without bothering the user).

Examples

Read 'Bearer <token>' from the Authorization header

const headers = { Authorization: "Bearer abc.def.ghi" };
const header = headers.Authorization || "";
const [scheme, token] = header.split(" ");
console.log(scheme, token); // Bearer abc.def.ghi
Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← Sessions vs tokens: where the credential livesSecurity best practices →