060
LVL 03 — MID DEVELOPER SESSION 060 DAY 60

AUTHEN TICATION

🎫 PIXELCRAFT-047
🔒 Security | 🟠 Hard | Priority: 🔴 Critical

There's no concept of "users" or "ownership." Anyone can access any image. Critical security flaw. Implement user authentication.
CONCEPTS.UNLOCKED
🔐
Authentication vs Authorization
Authentication: who are you? (login). Authorization: what can you do? (permissions). Two separate concerns that work together to secure your application.
🔒
Password Hashing
NEVER store plain text passwords. bcrypt hashes "password123" into an irreversible string. To verify, hash the input and compare hashes. One-way function — cannot be reversed.
🎫
JWT (JSON Web Tokens)
Stateless authentication tokens. Server signs a token containing the user ID. Client stores it and sends it with every request. Server verifies the signature — no session storage needed.
🔄
Login Flow
Credentials → server validates → returns JWT → client stores → sends with every request. The token proves identity without re-entering credentials.
🛡
Protected Routes
Middleware that verifies the JWT before the route handler runs. No valid token → 401 Unauthorized. Valid token → req.userId is set, handler proceeds.
Auth Middleware Pattern
A reusable function: extract token from header → verify signature → attach userId to request → call next(). Applied to any route that needs authentication.
HANDS-ON.TASKS
01
Registration Endpoint
npm install bcryptjs jsonwebtoken const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); app.post('/api/auth/register', async (req, res) => { try { const { name, email, password } = req.body; // Check if user exists const existingUser = await User.findOne({ email }); if (existingUser) return res.status(400) .json({ error: 'Email already registered' }); // Hash password (NEVER store plain text!) const salt = await bcrypt.genSalt(10); const hashedPassword = await bcrypt.hash(password, salt); const user = await User.create({ name, email, password: hashedPassword }); // Generate JWT const token = jwt.sign( { userId: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' } ); res.status(201).json({ token, user: { id: user._id, name, email } }); } catch (error) { res.status(500) .json({ error: 'Registration failed' }); } });
02
Login Endpoint
app.post('/api/auth/login', async (req, res) => { const { email, password } = req.body; const user = await User.findOne({ email }); if (!user) return res.status(401) .json({ error: 'Invalid credentials' }); const validPassword = await bcrypt.compare( password, user.password ); if (!validPassword) return res.status(401) .json({ error: 'Invalid credentials' }); const token = jwt.sign( { userId: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' } ); res.json({ token, user: { id: user._id, name: user.name, email } }); });
Same error message for "user not found" and "wrong password." Never reveal which part failed — that tells attackers whether an email is registered.
03
Auth Middleware
function authenticate(req, res, next) { const authHeader = req.headers.authorization; if (!authHeader?.startsWith('Bearer ')) { return res.status(401) .json({ error: 'No token provided' }); } try { const token = authHeader.split(' ')[1]; const decoded = jwt.verify( token, process.env.JWT_SECRET ); req.userId = decoded.userId; next(); } catch (error) { res.status(401) .json({ error: 'Invalid token' }); } }
04
Protect Routes
app.get('/api/images', authenticate, async (req, res) => { const images = await Image.find({ owner: req.userId }); res.json(images); });
authenticate runs first. If the token is valid, req.userId is set and the handler sees only that user's images. No token → 401. Invalid token → 401. Users can only see their own data.
05
Build Login/Register in React
const login = async (email, password) => { const res = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }), }); const data = await res.json(); localStorage.setItem('token', data.token); setUser(data.user); };
06
Close the Ticket
git switch -c feature/PIXELCRAFT-047-auth git add server/ src/ git commit -m "Add JWT auth with register, login, protected routes (PIXELCRAFT-047)" git push origin feature/PIXELCRAFT-047-auth # PR → Review → Merge → Close ticket ✅
CS.DEEP-DIVE

Cryptographic hashing.

bcrypt produces a one-way hash. You cannot reverse it. This is how EVERY secure system stores passwords.

// The same hashing principle protects:

Passwords        → bcrypt one-way hash
Blockchain       → integrity via hashes
Digital signatures → verify authenticity
File checksums   → sha256sum
Git commit IDs   → SHA-1 hashes

// JWTs: base64-encoded JSON with a
// cryptographic signature — the server
// can verify it wasn't tampered with.
"Security Lab"
[A] Add password strength validation: minimum 8 chars, at least one uppercase, one number, one special character. Use Zod on the server side (from Session 53).
[B] Decode a JWT at jwt.io — see the header, payload (userId, expiration), and signature. Understand what's inside the token your server generates.
[C] Add a "forgot password" flow: generate a reset token, send a reset link (console.log for now), verify token, allow password change. Research secure token generation.
REF.MATERIAL
ARTICLE
Auth0
Official JWT guide: structure (header, payload, signature), how signing works, when to use JWTs, and the interactive debugger.
JWTOFFICIALESSENTIAL
VIDEO
Web Dev Simplified
Practical JWT walkthrough: creating tokens, verifying, refresh tokens, and common security mistakes to avoid.
JWTPRACTICAL
ARTICLE
OWASP Foundation
Industry best practices: bcrypt, scrypt, Argon2. Why MD5/SHA are NOT for passwords. The security standard for password storage.
SECURITYOWASPBEST PRACTICES
VIDEO
Fireship
Sessions vs JWTs: tradeoffs, when to use each, and why modern APIs prefer stateless tokens.
AUTHCOMPARISON
ARTICLE
Wikipedia
The algorithm: Blowfish-based, adaptive cost factor, built-in salt. Why bcrypt is the gold standard for password hashing.
BCRYPTCRYPTOGRAPHYCS
// LEAVE EXCITED BECAUSE
PixelCraft has users! Register, log in, see only YOUR images. Nobody can access your work without your token. You built real security.