AiTechWorlds
AiTechWorlds
Authentication is one of the most important and most misunderstood parts of web development. Three approaches dominate modern web apps — each with different tradeoffs around security, complexity, and scalability. Understanding which to use and why is essential for building production applications.
The server creates a session and stores it in a database. The browser gets a session ID in a cookie.
1. User logs in with email + password
2. Server verifies credentials
3. Server creates a session record in the database: { sessionId, userId, createdAt, expiresAt }
4. Server sets a cookie: session=abc123
5. Browser sends cookie on every subsequent request
6. Server looks up session in database to identify the user
Pros:
Cons:
Instead of a session ID that points to data on the server, the token itself contains the user's data, cryptographically signed.
1. User logs in
2. Server creates a JWT: { userId, email, role } signed with a secret key
3. Browser stores the JWT (cookie or localStorage)
4. Browser sends JWT on every request
5. Server verifies the signature — no database lookup needed
6. Server reads the user data directly from the token
JWT structure: header.payload.signature
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.signature
Pros:
Cons:
Mitigation for revocation: Use short expiry (15 min) with a refresh token stored in an HttpOnly cookie. The refresh token can be blacklisted in a database if needed.
Delegate authentication to a trusted provider (Google, GitHub, Apple). You never handle passwords yourself.
1. User clicks "Continue with Google"
2. Browser redirects to Google's auth server
3. User authenticates with Google
4. Google redirects back with an authorization code
5. Your server exchanges the code for an access token
6. Your server fetches user info from Google
7. Your server creates or updates a user record
8. Your server creates a session (or JWT) for the user
Pros:
Cons:
This comes up constantly. The answer is: HttpOnly cookies.
HttpOnly cookie:
✅ Not accessible via JavaScript (immune to XSS)
✅ Sent automatically with every request
✅ Has SameSite protection against CSRF
✅ Works with server-side auth checks
localStorage:
❌ Accessible by ANY JavaScript on the page
❌ Stolen by XSS attacks
❌ Manual management (add to every fetch call)
⬜ Easier to implement
Store your JWT or session token in an HttpOnly, Secure, SameSite=Lax cookie:
// Set cookie in Node.js/Express
res.cookie("session", token, {
httpOnly: true, // not accessible via JS
secure: true, // HTTPS only
sameSite: "lax", // CSRF protection
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
});
// Set cookie in Next.js
cookies().set("session", token, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
maxAge: 60 * 60 * 24 * 7,
});
Never store plaintext passwords. Always hash with bcrypt:
import bcrypt from "bcryptjs";
// Creating a user
const hashedPassword = await bcrypt.hash(password, 12);
// 12 is the salt rounds — higher = slower but more secure (10-12 is standard)
await db.user.create({ data: { email, password: hashedPassword } });
// Verifying a password
const isValid = await bcrypt.compare(inputPassword, storedHash);
if (!isValid) throw new Error("Invalid password");
Never use MD5, SHA1, or SHA256 for passwords. These are fast — bcrypt is intentionally slow, making brute-force attacks infeasible.
For most Next.js applications:
Just cookies + your own auth logic: Best for full control, learning, or when you want to understand what's happening. More code to write.
NextAuth.js v5 (Auth.js): Excellent for production. Handles OAuth providers, sessions, JWT rotation, and database adapters. Minimal configuration.
Clerk: Hosted auth service. Zero backend auth code. Handles everything including user management UI. Higher monthly cost at scale.
Supabase Auth: If you're already using Supabase for your database, their auth is well-integrated and free to a generous limit.
NextAuth.js v5 defaults to JWT sessions stored in cookies. No database required for sessions. If you need to revoke sessions (important for admin-facing apps), configure a database adapter to store sessions.
NextAuth.js flow:
1. User signs in (credentials or OAuth)
2. NextAuth creates a JWT session token
3. Token is set as an HttpOnly cookie
4. Server Components can call auth() to get the session
5. Middleware can check the session before serving routes
Next lesson: NextAuth.js v5 setup — implementing production authentication in 30 minutes.
Get this course's notes on Telegram!
Free cheat sheets, summaries & practice exercises