Security

Common Authentication Vulnerabilities and How to Prevent Them

Credential stuffing, broken session handling, JWT confusion attacks, account enumeration, and the other ways login systems get broken in production — plus the concrete fixes for each.

Emilian GheoneaMay 28, 2026 4 min read

Authentication is the front door of every application, which is exactly why attackers spend so much time on it. The good news is that most real-world auth breaches don't come from exotic cryptography failures — they come from a short list of well-understood mistakes that keep getting repeated. This article walks through the most common ones and the concrete fixes for each.

1. Weak password storage

The classic failure: storing passwords in plaintext, or hashing them with a fast algorithm like MD5 or SHA-256. Fast hashes are a gift to attackers — a modern GPU can compute billions of SHA-256 hashes per second, so a leaked database is cracked in hours.

The fix. Use a slow, salted, memory-hard password hashing function designed for the job: bcrypt, scrypt, or Argon2id. These are deliberately expensive to compute, which makes offline brute-forcing impractical.

// Bad
hash = sha256(password)

// Good
hash = bcrypt(password, costFactor = 12)

Never invent your own scheme, never reuse a single global salt, and tune the cost factor so a single hash takes ~250ms on your hardware.

2. Credential stuffing

Users reuse passwords. When a different site is breached, attackers take those leaked email/password pairs and replay them against your login endpoint. Because the credentials are valid somewhere, a percentage will work on your site too.

The fix.

  • Rate-limit login attempts per IP and per account.
  • Add bot detection (reCAPTCHA or similar) after a few failed attempts.
  • Check new passwords against known-breached lists (the Have I Been Pwned k-anonymity API lets you do this without sending the full password).
  • Offer and encourage multi-factor authentication — it neutralizes stolen passwords almost entirely.

3. Account enumeration

Small differences in your responses can tell an attacker whether an email is registered. "No account with that email" versus "Wrong password" hands them a list of valid users to target. Even response timing can leak this.

The fix. Return identical responses and status codes whether or not the account exists — "If an account exists for that email, we've sent a reset link." Keep response times constant by performing a dummy hash comparison even when the user isn't found.

4. Broken session management

Sessions get attacked in several ways:

  • Session fixation — the attacker sets a known session ID before login and reuses it after.
  • Predictable tokens — session identifiers generated from weak randomness can be guessed.
  • Sessions that never expire — a stolen token works forever.

The fix.

  • Generate session IDs from a cryptographically secure random source (at least 128 bits of entropy).
  • Rotate the session identifier on every privilege change, especially right after login.
  • Set short idle timeouts and absolute lifetimes, and support server-side revocation.
  • Store session cookies with HttpOnly, Secure, and an appropriate SameSite attribute.

5. JWT misuse

JSON Web Tokens are powerful and easy to misuse. The two famous footguns:

  • The alg: none attack — some libraries accepted tokens with the algorithm set to none, skipping signature verification entirely.
  • Algorithm confusion (RS256 → HS256) — an attacker changes the header from RS256 to HS256 and signs the token using the server's public key as the HMAC secret. If your library naively uses "the key" for whatever algorithm the token claims, the forgery validates.

The fix.

  • Pin the expected algorithm server-side. Never trust the alg value from the token to decide how to verify it.
  • Reject none outright.
  • Prefer asymmetric signing (RS256/ES256) so verification keys can be public while signing keys stay private.
  • Keep access tokens short-lived and validate exp, iss, and aud on every request.

6. Insecure password reset

Password reset is authentication's back door. Weaknesses include predictable reset tokens, tokens that don't expire, reset links leaked through the Referer header, and host-header poisoning that sends the reset link to an attacker's domain.

The fix.

  • Generate high-entropy, single-use reset tokens with a short expiry (15–60 minutes).
  • Invalidate the token immediately after use and after a password change.
  • Build reset URLs from a server-side configured base URL, never from the incoming Host header.
  • Notify the user by email whenever their password changes.

7. Missing brute-force protection on secondary flows

Teams often rate-limit the main login form but forget the OTP verification endpoint, the "resend code" action, or the API token endpoints. A six-digit OTP with no attempt limit is trivially brute-forced.

The fix. Apply rate limiting and lockout consistently across every authentication-adjacent endpoint — sign-in, OTP verify, magic-link request, reset, and refresh.

8. Tokens exposed to the front end

Storing long-lived tokens in localStorage exposes them to any cross-site scripting (XSS) bug on your page. One injected script and the attacker exfiltrates the token.

The fix. Prefer HttpOnly cookies for session tokens so JavaScript can't read them. If you must use bearer tokens in a SPA, keep them in memory, keep them short-lived, and pair them with a refresh mechanism guarded by a secure cookie. And of course — fix the XSS.

A defensive checklist

  • Passwords hashed with bcrypt/scrypt/Argon2id, never a fast hash.
  • Rate limiting and lockout on all auth endpoints.
  • Identical responses and timing to prevent enumeration.
  • Session IDs rotated on login; cookies HttpOnly + Secure + SameSite.
  • JWT algorithm pinned server-side; none rejected; exp/iss/aud checked.
  • Reset tokens single-use, short-lived, built from a trusted base URL.
  • MFA available and encouraged.
  • Security headers and a tight Content-Security-Policy to limit XSS blast radius.

None of these fixes are exotic. The reason these vulnerabilities persist is that authentication is usually built once, early, under time pressure — and then never revisited. Treating auth as a security surface that deserves ongoing attention is the single biggest improvement most teams can make.

Written by

Emilian Gheonea

Senior Blockchain & Full-Stack Software Engineer. I build EmbedAuth — an embeddable authentication platform for SaaS — and write about the auth problems most teams hit too late.