Thuta Learning
ProjectsWeb Developmentbeginner

Project: Cookie, Session, and Auth Flow Demo

What you'll walk away with

  • Explain the core ideas behind Project: Cookie, Session, and Auth Flow Demo
  • Read the diagram and trace how a request, piece of data, or event flows through the system
  • Explain how this piece connects into the larger web architecture picture

Build the mental model

This project combines the cookies-and-sessions lesson with authentication versus authorization. The simulation is in-memory only and is not a real login-system template — per the password-security lesson, use bcrypt/Argon2 or Auth0/Clerk in a real project.

Because HTTP is stateless, the server creates a session record after login and hands the browser a cookie holding the session ID, which the browser auto-attaches to every later request.

ConceptAnswers the question
AuthenticationWho is this? Happens once at login, then implicitly on every successful session lookup
AuthorizationIs this identified user allowed to do this specific thing? Checked per request/action

Not a production auth template

This code exists only to show the concept, and skips password hashing, cookie security flags (HttpOnly, Secure, SameSite), and session expiry — use an established library or provider for a real system.

Watching both requests side by side is the point: the admin action fails not because the session or cookie is broken, but because authorization rules say so.

text
AUTHENTICATION VS AUTHORIZATION FLOW
------------------------------------
AUTH FLOW: LOGIN -> SESSION -> COOKIE -> AUTHORIZATION CHECK
----------------------------------------------------------------
[User] --1. login(username, password)--> [Backend]
                                             |
                                   2. verify credentials
                                             |
                                   3. create session record
                                      (id -> user, role)
                                             |
                                   4. Set-Cookie: session_id=X
                                             v
                                   [Browser stores cookie]
                                             |
                    (cookie is attached automatically to later requests)
                                             v
[Request N] --Cookie: session_id=X--> [Backend]
                                             |
                                   5. session lookup (authN)
                                             |
                                   6. authorization check (authZ)
                                             |
                          +------------------+------------------+
                          |                                     |
                      allowed                                denied
                          v                                     v
                    200 OK response                      403 Forbidden

Connect it to a real scenario

Read the code before running it and predict the output: alice (a normal user) and bob (an admin) both log in and then attempt a 'delete-user' action.

Alice logs in

Backend verifies her password, creates a session record, and returns a cookie-like string carrying the session ID.

Request 1: view-dashboard

Using alice's cookie, the session lookup succeeds and the action is allowed.

Request 2: delete-user (denied)

Alice is still authenticated, but her role is 'user', so the authorization check denies the action with a 403.

Bob logs in

A new session is created for bob, whose role is 'admin', with its own session ID.

Request 3: delete-user (allowed)

Bob's session passes both the authentication and authorization checks, so the action is allowed.

Run the code, then change bob's role to 'user' and rerun it to confirm the denial logic reacts correctly.

Try the working example

javascript
// Mock user 'database'. In a real system, passwords are never stored or
// compared in plaintext -- see the password-security lesson and use an
// established library (bcrypt, Argon2) or an auth provider (Auth0, Clerk).
const users = {
  alice: { password: 'hunter2', role: 'user' },
  bob: { password: 'adminpass', role: 'admin' },
};

// In-memory session store: sessionId -> { username, role }
const sessions = {};
let sessionCounter = 0;

function createSessionId() {
  sessionCounter += 1;
  return `sess_${sessionCounter}`;
}

function login(username, password) {
  const user = users[username];
  if (!user || user.password !== password) {
    return { ok: false, reason: 'invalid credentials' };
  }
  const sessionId = createSessionId();
  sessions[sessionId] = { username, role: user.role };
  return { ok: true, cookie: `session_id=${sessionId}` };
}

function request(cookie, action) {
  const sessionId = cookie.split('=')[1];
  const session = sessions[sessionId];
  if (!session) {
    return { status: 401, body: 'not authenticated' };
  }
  // Authentication (who are you) already passed. This is authorization
  // (are you allowed to do THIS specific thing).
  if (action === 'view-dashboard') {
    return { status: 200, body: `${session.username} viewed the dashboard` };
  }
  if (action === 'delete-user') {
    if (session.role !== 'admin') {
      return {
        status: 403,
        body: `${session.username} is authenticated but NOT authorized (needs admin)`,
      };
    }
    return { status: 200, body: `${session.username} deleted a user` };
  }
  return { status: 404, body: 'unknown action' };
}

const aliceLogin = login('alice', 'hunter2');
console.log('Login (alice):', aliceLogin);

console.log('Request 1 (view-dashboard):', request(aliceLogin.cookie, 'view-dashboard'));
console.log('Request 2 (delete-user):   ', request(aliceLogin.cookie, 'delete-user'));

const bobLogin = login('bob', 'adminpass');
console.log('Login (bob):  ', bobLogin);
console.log('Request 3 (delete-user):   ', request(bobLogin.cookie, 'delete-user'));
You should see
Running the code makes authentication success (login, view-dashboard) and authorization denial (delete-user) concrete:

Login (alice): { ok: true, cookie: 'session_id=sess_1' }
Request 1 (view-dashboard): { status: 200, body: 'alice viewed the dashboard' }
Request 2 (delete-user):    { status: 403, body: 'alice is authenticated but NOT authorized (needs admin)' }
Login (bob):   { ok: true, cookie: 'session_id=sess_2' }
Request 3 (delete-user):    { status: 200, body: 'bob deleted a user' }

5-minute try-it

Add a third user with role 'moderator' who is allowed to view-dashboard and a new 'edit-post' action but not delete-user, and extend the authorization check to prove authentication and authorization are still independently checked.

One important caution

Using predictable session IDs (sess_1, sess_2...) like this demo in production — real session IDs must be cryptographically random

Conflating a 403 (authorization denial) with a 401 (not authenticated) as if they were the same kind of failure

OWASP Session Management Cheat SheetHow the Web Works

Easy traps

  • Using predictable session IDs (sess_1, sess_2...) like this demo in production — real session IDs must be cryptographically random
  • Conflating a 403 (authorization denial) with a 401 (not authenticated) as if they were the same kind of failure
  • This course is a system map, not a deep-dive on every piece -- for depth on REST, DNS/hosting, databases, or security, continue to the API Tutorial, Cloud & Deployment, SQL, or Cybersecurity tutorials.

Exercise

Add a third user with role 'moderator' who is allowed to view-dashboard and a new 'edit-post' action but not delete-user, and extend the authorization check to prove authentication and authorization are still independently checked.

You'll know it worked when: Running the code makes authentication success (login, view-dashboard) and authorization denial (delete-user) concrete: Login (alice): { ok: true, cookie: 'session_id=sess_1' } Request 1 (view-dashboard): { status: 200, body: 'alice viewed the dashboard' } Request 2 (delete-user): { status: 403, body: 'alice is authenticated but NOT authorized (needs admin)' } Login (bob): { ok: true, cookie: 'session_id=sess_2' } Request 3 (delete-user): { status: 200, body: 'bob deleted a user' }

Project: Cookie, Session, and Auth Flow Demo | Thuta Learning