Crimes (do not commit)
// ❌ localStorage
localStorage.setItem("password", "hunter2");
// ❌ sessionStorage
sessionStorage.token = jwt;
// ❌ Cookies without HttpOnly
// document.cookie = "token=" + jwt;
// ❌ In source control
// const API_KEY = "ABCD-1234-LEAKED";
Bonus offense: committing secrets to a public repo and adding a sticker that says “No peeking”.
Minimal “do it right” login flow
Client → POST /login (over HTTPS)
Server → Verify creds → Create session in DB/Redis → Set HttpOnly cookie
Client → Subsequent requests send cookie automatically
Server → Authorize per-request based on session → Return data
Logout → Server deletes session + sets expired cookie
Need APIs across subdomains? Use SameSite=None; Secure with strict CORS, and still keep tokens out of JS.