How Authentication Works in Web Applications

Security

In this post, let's understand how authentication in web applications works.

We'll cover two common approaches:

  • Session based authentication
  • Token based authentication (usually JWT)

The Core Problem Authentication Solves

Imagine a server as a guarded building.

Before you're allowed inside, you need to prove who you are. Once you've proven it, the server needs a reliable way to recognize you again on every subsequent request without asking for your username and password each time.

That "recognition" is what authentication mechanisms provide.

Security Essentials

Before diving into the mechanisms, two critical requirements:

HTTPS is mandatory. Sending credentials or tokens over HTTP means they can be intercepted in transit. Authentication must always happen over encrypted connections.

Passwords are never stored directly. Servers store salted hashes (using bcrypt, Argon2, or similar) that can verify but not reveal the original password. When you log in, the server hashes your input and compares it to the stored hash never the plaintext password.

Session Based Authentication

What Actually Happens

  1. A user enters their username and password on a login page.
  2. The browser sends these credentials to the server.
  3. The server verifies them against its database.
  4. If they match, the server creates a session.
  5. The server sends back a session ID inside a cookie.
  6. The browser stores this cookie automatically.
  7. From this point onward, every request the browser makes includes that cookie.

Note: You don't need to set the cookie manually in subsequent requests. Your browser automatically includes it on all requests that match the cookie's domain.

The cookie itself does not contain user data. It simply contains a session identifier.

Where the State Lives

On the server.

When the server issues a session ID, it also stores something like this internally:

  • Session ID → User ID
  • Session status (active / expired)
  • Optional metadata (timestamps, IP, etc.)

Every incoming request follows this flow:

  1. Read the session ID from the cookie
  2. Look it up in the server's session store
  3. Verify that the session is still valid

As long as that session exists and is active, the user is authenticated.

This is why session based authentication is called stateful. The server is actively tracking who is logged in.

Client
Server
Database
  • No cookie yet
    • users
      42 → pw hash

    Login·Step 1 of 7

    Client sends credentials

    Client → ServerPOST /login { email, password }

    The username and password travel to the server over HTTPS.

    Session-based login: the server stores the session and looks it up on every request.

    Logging Out

    When a user logs out:

    1. The client sends a logout request to the server
    2. The server deletes the session from the database
    3. The server responds with success
    4. The client removes the cookie

    Since the session is deleted from the server's session store, any subsequent requests with that session ID will be rejected.

    Client
    Server
    Database
    • Cookie
      sid=abc123
      • users
        42 → pw hash
      • sessions
        abc123 → user 42

      Logout·Step 1 of 7

      Client asks to log out

      Client → ServerPOST /logout · Cookie: sid=abc123

      The logout request carries the session cookie like any other.

      Session logout: deleting the session on the server makes the old ID worthless.

      Token Based Authentication (JWT)

      Token based authentication follows a very similar start, but a very different continuation.

      What Happens During Login

      1. The user enters their username and password.
      2. The browser sends them to the server.
      3. The server validates the credentials.
      4. Instead of creating a session, the server generates a token.
      5. Most commonly, this token is a JWT (JSON Web Token).
      6. The token is returned to the client and stored either:
        • In memory
        • In local storage
        • Or sometimes in a cookie

      What's Inside the Token

      A JWT contains:

      • User identification (e.g., user ID)
      • Optional metadata (roles, expiry time)
      • A cryptographic signature

      The signature is created using a secret key known only to the server.

      This is the critical part.

      Making Authenticated Requests

      For every subsequent request:

      1. The client sends the token in the Authorization header
      2. Typically as: Authorization: Bearer <token>

      When the server receives the request:

      1. It verifies the token's signature using its secret
      2. It checks expiry and validity
      3. If valid, the request is authenticated

      No database lookup is required.

      The server does not store session state.

      This is why token based authentication is called stateless.

      Why the Token Can't Be Tampered With

      Any changes to the token content modifies the signature, causing signature verification to fail on the server.

      Since the client doesn't have the secret key, any tampering to the token is impossible. The client cannot create a valid signature for modified content.

      This guarantees integrity without requiring server side storage.

      Client
      Server
      Database
      • No token yet
      • Secret key
        ••••••••
      • users
        42 → pw hash

      Login·Step 1 of 10

      Client sends credentials

      Client → ServerPOST /login { email, password }

      The username and password travel to the server over HTTPS.

      Token-based login: the server signs a JWT and later verifies it without a database lookup.

      Logging Out

      Token based logout is simpler because there's no server side session to invalidate:

      1. The client simply removes the token from storage (memory/localStorage)
      2. No server communication is required

      The token becomes useless once removed. However, if the token is stolen before logout, it remains valid until expiry.

      If it's critical for your app to not allow requests from a token after logout, you can blacklist the token by adding revoked tokens to an in memory database.

      The other solution is to have access tokens with short validity periods, limiting the window of risk.

      Client
      Servernot used
      Databasenot used
      • No token
      • Secret key
        ••••••••
      • users
        42 → pw hash

      Logout·Step 1 of 4

      Client deletes the token

      ClientlocalStorage.removeItem("token")

      That's the whole logout. No request is sent to the server.

      Token logout: the client forgets the token, but copies stay valid until they expire.

      Key Differences at a Glance

      AspectSession BasedToken Based
      Server stateStored on serverNot stored
      ScalabilityHarder (shared state)Easier
      Cookie usageRequiredOptional
      RevocationEasyHarder
      StatelessNoYes

      Final Thoughts

      Both approaches exist for good reasons.

      Session based authentication is simple, intuitive, and easy to revoke.

      Token based authentication scales better and works naturally with distributed systems.

      The important part isn't choosing one blindly. It's understanding where the state lives, how identity is verified, and what trade-offs you're making.

      Once that's clear, authentication stops feeling like magic and starts feeling like engineering.

      7cd8770b-ee9c-4267-9ecb-28cdcd8eb7f0