StackDevLife
Cover image for: Session Hijacking Starts With Your Cookies — Here's What You Missed
Back to Blog

Session Hijacking Starts With Your Cookies — Here's What You Missed

Most developers think session hijacking is an advanced attack. It's not. It usually starts with something very basic: your cookies. Learn the 3 flags and token refresh pattern that actually works.

SB

Sandeep Bansod

April 21, 20268 min read
Share:
Most developers think session hijacking is some "advanced hacker attack".
It's not.
It usually starts with something very basic: your cookiesyour cookies

A Small Mistake That Becomes a Big Problem

A real situation I've seen:

  • App was using JWT stored in cookies
  • Everything worked fine in dev and staging
  • Deployed to production
  • But:

👉 Cookies were not marked Secure
👉 Someone on the same network intercepted traffic
👉 Session got reused

No password needed. No brute force. Just cookie reuse.

🤔 Why Cookies Matter More Than You Think

When you log in:

  1. Server gives you a session or token
  2. Browser stores it (usually in cookies)
  3. Every request automatically includes it

👉 That cookie is your identityThat cookie is your identity

If someone gets it → they are you.

How Session Hijacking Actually Happens

A clean diagram showing how session
A clean diagram showing how session

Common real-world paths:

1. Network Interception (HTTP / insecure setups)

  • Using public WiFi
  • Traffic not encrypted properly
  • Cookies sent in plain text

2. XSS (Cross-Site Scripting)

JavaScript
document.cookie

If your cookie is readable → attacker can steal it.

3. CSRF (Cross-Site Request Forgery)

Browser automatically sends cookies:

👉 Even when request is triggered from another site

4. Token Leakage (logs / frontend)

  • Logging tokens accidentally
  • Exposing via frontend (localStorage, window)

The Problem Most JWT Articles Don't Explain

Everyone talks about:

  • "Use JWT"
  • "Store token"
  • "Use refresh token"

But they don't tell you:

👉 Where you store the token matters more than the token itselfWhere you store the token matters more than the token itself

Illustration of a browser blocking JavaScript
Illustration of a browser blocking JavaScript

1. HttpOnly — Protect Against XSS

What it does:

👉 Prevents JavaScript from accessing cookies

PLAIN
Set-Cookie: token=abc123; HttpOnly

Why it matters:

Even if XSS exists:

JavaScript
document.cookie // ❌ cannot access HttpOnly cookies

2. Secure — Only Over HTTPS

Comparison illustration of HTTP vs HTTPS
Comparison illustration of HTTP vs HTTPS

What it does:

👉 Cookie is sent ONLY over HTTPS

PLAIN
Set-Cookie: token=abc123; Secure

Why it matters:

  • Prevents MITM attacks
  • Protects on public networks

3. SameSite — Protection Against CSRF

Diagram showing SameSite cookie protection preventing cross-site
Diagram showing SameSite cookie protection preventing cross-site

Options:

PLAIN
SameSite=Strict   // safest
SameSite=Lax      // balanced
SameSite=None     // required for cross-domain (must use Secure)

Why it matters:

👉 Prevents browser from sending cookies in cross-site requests

PLAIN
Set-Cookie: accessToken=xyz;
HttpOnly;
Secure;
SameSite=Strict;
Path=/;

👉 This should be your default baseline

🔄 Token Refresh Pattern (Where Most Apps Fail)

Many apps do this wrong:

PLAIN
❌ Store long-lived JWT in browser
❌ No refresh logic
❌ Token valid for days

✅ Correct Pattern

Access Token

  • Short-lived (5–15 min)
  • Stored in HttpOnly cookie

Refresh Token

  • Longer-lived
  • Stored securely (also HttpOnly cookie)

Flow:

  • User logs in
    • Server sends:
      • accessToken (short life)
      • refreshToken (long life)
  • When access token expires:
    • frontend calls /refresh
    • server verifies refresh token
    • issues new access token

👉 Even if access token leaks → damage is limited

Common Mistakes (I See This A LOT)

❌ Storing JWT in localStorage

JavaScript
localStorage.setItem("token", token);

👉 Easily accessible via XSS

❌ Missing Secure flag in production

👉 Works in dev → breaks security in prod

❌ Using SameSite=None without Secure

👉 Browser may reject or expose cookie

❌ Logging tokens

JavaScript
console.log(req.headers.authorization);

👉 Logs = permanent leak

❌ Sharing tokens across subdomains without isolation

👉 One compromised app = all sessions compromised

How This Connects To Your Previous JWT Article

Your JWT article likely covered:

JWT authentication flow with access token and refresh token
JWT authentication flow with access token and refresh token
  • Token generation
  • Signing
  • Validation

This article completes it:

👉 Storage + transport securityStorage + transport security

Because:

A perfectly signed JWT is useless if it's stolen.

Practical Setup (Based on Your Stack)

You are using:

  • Next.js
  • Node.js
  • Backend (Node.js / Express)

Express setup:

JavaScript
res.cookie("accessToken", token, {
  httpOnly: true,
  secure: true,
  sameSite: "strict",
});

Next.js (API routes)

Use cookies, NOT localStorage.

Docker / NGINX

👉 Ensure HTTPS termination is correct

👉 Otherwise Secure flag won't work properly

Final Thought

Most developers secure:

  • Passwords
  • APIs
  • Database

But forget:

👉 the thing that represents the user session

And that's the easiest entry point.

🚀 What You Should Do Today

  1. Check your cookies in DevTools
  2. Verify flags:
    1. HttpOnly ✅
    2. Secure ✅
    3. SameSite ✅
  3. Remove tokens from localStorage
  4. Implement refresh token flow

Enjoying this article?

Get new articles, tips, and fixes delivered straight to your inbox — free, no spam.

Was this article helpful?

Let me know if this was useful — it helps me write more content like this.

Found this useful? Share it.

XLinkedInHN
SB

Sandeep Bansod

I'm a Front-End Developer located in India focused on making websites look great, work fast and perform well with a seamless user experience. Over the years I've worked across different areas of digital design, web development, email design, app UI/UX and development.

Comments

Leave a Comment

All comments are reviewed before publishing

0/2000

Email is private and never published

Related Articles

You might also enjoy these

Level up your dev skills — weekly

Practical tutorials, quick fixes, and tools that save you hours.Join developers who read Stack Dev Life every week. Free, no spam.