Broken Authentication
In one line: Authentication is proving who you are, and it breaks in predictable ways — passwords reused from other breaches (credential stuffing), session tokens that can be stolen or forged, and missing or bypassable second factors — so the defenses are strong credential handling, robust session management, and MFA.
Authentication is the front door's question: "are you really who you claim to be?" Every app answers it — usually with a password, then a session so you don't re-type it on every click. Things go wrong in two broad ways. First, the credential is weak or already known to attackers: people reuse the same password everywhere, so one site's breach unlocks dozens of accounts. Second, the session — the token that says "this browser is logged in as Alice" — gets stolen, guessed, or forged, letting an attacker become Alice without ever knowing her password. This lesson is about both: how login and sessions actually work, the specific ways they fail, and what hardened modern authentication looks like. (This is the identity cluster of the OWASP Top 10 — A07.)
Two halves: credentials and sessions
Authentication has two phases, each with its own failure modes:
- Login — verifying a credential (password, passkey, OAuth token) once.
- Session — remembering that verification across subsequent requests, because HTTP is stateless (each request is independent). After login the server issues a session token the client sends with every later request to prove "I already logged in."
Break either and the attacker is in.
- Authentication (authn) — proving who you are. (Distinct from authorization — what you're allowed to do — the next lesson.)
- Credential — the secret/proof you log in with: password, passkey, one-time code.
- Session token — the value (often a cookie or JWT) that represents a logged-in session on later requests.
- Credential stuffing — automated login attempts using username/password pairs leaked from other sites, exploiting password reuse.
- Brute force — trying many passwords against one account; password spraying — trying one common password against many accounts (to dodge lockouts).
- MFA (Multi-Factor Authentication) — requiring two+ independent factors: something you know (password), have (phone/passkey), or are (biometric).
- JWT (JSON Web Token) — a self-contained, signed token carrying claims (who you are), verifiable without a server-side lookup. Powerful and easy to misuse.
- Session fixation — an attack where the attacker sets a victim's session ID before login and reuses it after.
How credentials get broken
- Credential stuffing (the big one). Billions of username/password pairs from past breaches are public. Attackers replay them at scale; because people reuse passwords, a meaningful percentage work. This — not clever cracking — is how most account takeovers happen.
- Weak password storage. If your DB is breached and passwords were stored with a fast or unsalted hash, they're cracked en masse — turning your breach into every other site's breach via reuse. (Use a slow salted KDF — see hashing.)
- Brute force / spraying. Unlimited login attempts let attackers guess weak passwords. Rate limiting and lockouts are the counter.
- Weak reset flows. A "forgot password" feature with guessable tokens, no expiry, or leaky responses is often the weakest door — attackers target it instead of the login.
A breach at SiteX leaks alice@example.com : Summer2023!. Alice reused it on your app. An attacker:
- Loads millions of leaked pairs into a tool.
- Fires them at your login from rotating IPs, slowly enough to dodge naive rate limits.
- A fraction succeed — including Alice's — and those accounts are now the attacker's.
Notice no password was "cracked" and your hashing was irrelevant — the credential was already valid. The defenses that actually stop this: MFA (a stolen password isn't enough), breached-password checks (reject known-leaked passwords at signup), bot/rate-limit defenses, and anomaly detection (impossible-travel logins). This is why MFA is the single highest-leverage authentication control.
How sessions get broken
Once logged in, the session token is as good as the password — anyone holding it is the user. Attacks:
- Session hijacking (theft). Steal the token via XSS (if it's readable by JS), network sniffing (if not HTTPS), or malware. Defenses:
HttpOnly(JS can't read it),Secure(HTTPS only),SameSite(limits cross-site sending), short lifetimes, and rotation on privilege change. - Predictable tokens. If session IDs are sequential or low-entropy, attackers guess valid ones. Tokens must be long and from a CSPRNG.
- Session fixation. The app reuses a pre-login session ID after login, so an attacker who planted one rides in. Defense: issue a brand-new session ID at login.
- No expiry / no logout. Sessions that live forever or survive "log out" give stolen tokens unlimited value. Expire them; invalidate server-side on logout.
The JWT trap
JWTs are popular for stateless auth: a signed token the server can verify without a database lookup. They're powerful but have sharp edges that cause real breaches:
alg:none and weak-secret trapsA JWT has a header saying which algorithm signed it. Two classic failures:
- The
alg: nonebypass. Some libraries historically honored a token whose header said"alg":"none"— meaning unsigned. An attacker rewrites the token's claims to"role":"admin", setsalgtonone, strips the signature, and a naïve verifier accepts it. Always rejectnoneand pin the expected algorithm server-side. - Weak HMAC secret. If a JWT is signed with
HS256using a guessable secret, an attacker brute-forces the secret offline and then forges any token they like. Use a strong, random secret (or asymmetricRS256/ES256).
A deeper structural issue: a JWT can't be easily revoked before it expires, because verification is stateless (no lookup). If a token is stolen, it's valid until expiry. Mitigations: short lifetimes + refresh tokens, or a server-side revocation list (which gives up some of JWT's statelessness). Don't put JWTs in localStorage where XSS can read them; prefer HttpOnly cookies.
What hardened authentication looks like
- Require MFA, especially for admins and sensitive actions — the highest-leverage control, defeating credential stuffing and phishing of passwords alone. Phishing-resistant factors (passkeys/WebAuthn, hardware keys) beat SMS codes (which are SIM-swappable).
- Move toward passkeys. Passkeys (WebAuthn) replace passwords with device-bound public-key crypto — nothing reusable to steal or phish.
- Store passwords with a slow salted KDF (Argon2id/bcrypt) and reject known-breached passwords at signup.
- Rate-limit and bot-protect login and reset flows; alert on anomalies (impossible travel, spikes).
- Manage sessions properly: high-entropy tokens,
HttpOnly/Secure/SameSitecookies, new session ID at login, sensible expiry, real server-side logout. - Harden reset flows as carefully as login — single-use, short-lived, unguessable tokens; don't reveal whether an account exists.
Lock this distinction in now, because mixing them up causes bugs: authentication proves who you are (this lesson); authorization decides what you may do (next lesson). A system can authenticate you perfectly and still fail to check whether you're allowed to view a given record — a separate, even more common bug. Logging in correctly is necessary but not sufficient.
Why it matters
- It's the most-attacked door. Credential stuffing alone accounts for a huge share of account-takeover traffic; auth failures are A07 in the Top 10.
- One weak link cascades. Reused passwords and stealable sessions mean a failure here often is the breach — no further exploitation needed.
- MFA and passkeys are where the field is moving. Knowing why password-only auth is obsolete, and what replaces it, is core security-engineer judgment.
Common pitfalls
- Relying on passwords alone. Without MFA, credential stuffing wins eventually. Add MFA; prefer phishing-resistant factors.
- Storing passwords with fast/unsalted hashes. Turns your breach into everyone's. Use Argon2id/bcrypt and reject breached passwords.
- Treating session tokens casually. Missing
HttpOnly/Secure/SameSite, predictable IDs, no rotation at login, or eternal sessions all hand attackers the keys. - JWT misuse. Accepting
alg:none, weak secrets, no expiry, no revocation plan, or storing them where XSS can read them. Pin the algorithm, use strong keys, keep lifetimes short. - Ignoring the reset flow. It's often the weakest path to an account. Harden it as much as login.
- Confusing authn with authz. Verifying identity is not verifying permission — check both.
Page checkpoint
Did broken auth click?
Pass to unlock the Next button belowWhat's next
→ Continue to Broken Access Control — the other half of identity and the #1 category in the Top 10: once you know who a user is, how do you correctly enforce what they're allowed to do — and why this check is missed so often.
→ Going deeper: the cryptographic side of credentials is password hashing; enterprise identity (SSO, federation, passkeys at scale) is Cloud & Identity Security.