LECTURE: UNDERSTANDING COOKIES IN WEB DEVELOPMENT
MOTIVATION: WHY COOKIES MATTER
Hey everyone, welcome to today’s lecture! Today, we’re exploring cookies—those
small pieces of data you’ve likely seen pop up in “accept cookies” banners.
Cookies are key to how websites work, from keeping you logged in to remembering
your preferences. In this course, we’re working toward authentication (logging
in) and authorization (what you’re allowed to do), and cookies are a
foundational step for that.
Picture this: You’re using a Blog application. You log in to read posts, or
maybe you’re an admin editing them. How does the site remember you as you
navigate? Without cookies, every page load would be a fresh start—pretty
annoying, right? Cookies fix that by storing info on your device, acting like a
memory tag for the site.
Ever wonder why you stay logged in after closing your browser? Or why a site
“knows” you when you return? That’s cookies! But here’s a misconception: Some
think cookies are just for tracking or ads. Not quite—they’re tools, and their
use depends on the developer. Let’s dive in with our Blog application example
and build it up step-by-step.
--------------------------------------------------------------------------------
SECTION 1: WHAT ARE COOKIES, REALLY?
A cookie is a tiny text file a website saves on your device through your
browser. It’s like a note the site leaves itself, with a name, a value, and
optional settings—like how long it lasts or who can access it.
Here’s a misconception to shake up: People often think cookies hold big personal
details, like your email or password. Nope! They usually store simple stuff,
like an ID. In our Blog application, when you visit as a guest, it might set:
* Name: visitor_id
* Value: guest456
* Purpose: Marks you as a guest browsing public posts.
That’s super basic—no login yet. We’ll expand this as we go!
--------------------------------------------------------------------------------
SECTION 2: SETTING COOKIES WITH NEXT.JS
Cookies are a collaboration between the browser (client) and server. Here’s the
flow:
1. Server Sets a Cookie: Sends it via the Set-Cookie header.
2. Browser Stores It: Saves it locally.
3. Browser Sends It Back: Includes it in every request to the site.
4. Server Reads It: Uses it to recognize you.
In Next.js, we can use the cookies utility from next/headers to set and read
cookies. Let’s set a cookie server-side for a guest in our Blog application:
// app/api/set-guest/route.js
import { cookies } from 'next/headers';
export async function GET() {
cookies().set('visitor_id', 'guest456', {
path: '/', // Available site-wide
maxAge: 60 * 60, // 1 hour
});
return new Response(JSON.stringify({ message: 'Welcome, guest!' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
}
When you hit this route, the server sets Set-Cookie: visitor_id=guest456;
Max-Age=3600; Path=/. Your browser stores it, and every request after sends
Cookie: visitor_id=guest456.
Now, on the client side, let’s set a cookie for user preferences (e.g.,
filtering posts by tag). In a React component:
'use client';
// app/components/SetPrefs.js
import { useEffect } from 'react';
export default function SetPrefs() {
useEffect(() => {
document.cookie = 'prefs=tag:tech; path=/; max-age=86400'; // 1 day
}, []);
return <p>Preferences set to tech posts!</p>;
}
The browser now has prefs=tag:tech alongside visitor_id. We’ll handle reading
them next.
--------------------------------------------------------------------------------
SECTION 3: COOKIE SECURITY AND HTTPONLY
Cookies need protection—otherwise, they’re vulnerable. A big player here is
HttpOnly, which blocks JavaScript from accessing the cookie (e.g.,
document.cookie can’t see it). This guards against XSS (Cross-Site Scripting)
attacks, where hackers try to steal cookies.
Let’s secure an admin login cookie in Next.js:
// app/api/login/route.js
import { cookies } from 'next/headers';
export async function POST() {
// Imagine we verified username/password
const sessionId = 'abc789xyz';
cookies().set('session_id', sessionId, {
path: '/',
maxAge: 60 * 60, // 1 hour
httpOnly: true, // No JS access
secure: process.env.NODE_ENV === 'production', // HTTPS in prod
sameSite: 'strict', // Blocks CSRF
});
return new Response(JSON.stringify({ message: 'Logged in!' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
}
Security Features:
* HttpOnly: Keeps session_id safe from client-side scripts.
* Secure: Ensures HTTPS-only transmission (skip in dev, enforce in prod).
* SameSite=Strict: Prevents cross-site request forgery (CSRF).
General Security:
* Don’t store sensitive data (e.g., passwords)—use random IDs linked to server
data.
* Set expiration to limit exposure if stolen.
* Always use HTTPS to encrypt traffic—unencrypted cookies are easy targets.
--------------------------------------------------------------------------------
SECTION 4: HANDLING COOKIES CLIENT- AND SERVER-SIDE
Let’s use cookies in our Blog application. First, server-side, verify an admin
session:
// app/api/check-session/route.js
import { cookies } from 'next/headers';
export async function GET() {
const cookieStore = cookies();
const sessionId = cookieStore.get('session_id')?.value;
if (sessionId === 'abc789xyz') { // Check against a DB in real apps
return new Response(JSON.stringify({ message: 'Admin access granted' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
}
return new Response(JSON.stringify({ message: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' },
});
}
Now, client-side, read and display the prefs cookie:
'use client';
// app/components/DisplayPrefs.js
import { useState, useEffect } from 'react';
export default function DisplayPrefs() {
const [prefs, setPrefs] = useState('');
useEffect(() => {
const getCookie = (name) => {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
};
setPrefs(getCookie('prefs') || 'No preferences set');
}, []);
return <p>Your post filter: {prefs}</p>;
}
In action:
1. Admin logs in → session_id=abc789xyz (HttpOnly, server-only).
2. User sets prefs=tag:tech → Client reads it to filter posts.
Advantages: Easy to manage state, secure with proper flags. Disadvantages: Small
size limit (4KB), can be cleared, needs security care.
--------------------------------------------------------------------------------
CONCLUSION: KEY TAKEAWAYS
Let’s wrap up! Cookies power our Blog application—tracking guests, securing
admins, and personalizing views. We set visitor_id server-side, secured
session_id with HttpOnly, and handled prefs client-side.
Key Points:
* Cookies are name-value pairs shuttled between client and server.
* Use next/headers in Next.js or document.cookie on the client.
* Secure them with HttpOnly, Secure, and SameSite.
Pitfalls to Avoid:
* Don’t skip security—HttpOnly is critical for sessions.
* Avoid overloading cookies—keep data small and server-linked.
Next time, we’ll build on this for authentication and authorization. Questions?
Let’s talk!
Maggie is a generative AI that can help you understand the course content better. You can ask her questions about the lecture, and she will try to answer them. You can also see the questions asked by other students and her responses.
Join the discussion to ask questions, share your thoughts, and discuss with other learners