Skip to content

Chapter 13 of 204 min readBy Deepak GuptaPublished

Defending the Login

Your login endpoint is one of the most attacked URLs you own. Credential abuse was the top initial access vector in the 2025 Verizon Data Breach Investigations Report, at 22% of breaches. In the 2026 report it fell to 13%, overtaken by exploited vulnerabilities at 31%. (Verizon DBIR) Read that as attackers finding easier doors, not as login getting safe: stuffing, phishing, and recovery abuse have not stopped. Defend the login in layers, and assume each layer will sometimes fail.

Threat model in one table

Threat What the attacker does Primary defenses
Credential stuffing Replays leaked email and password pairs at scale Breached-password checks, risk scoring, bot defense, passkeys
Password spraying Tries a few common passwords across many accounts Blocklist of common passwords, per-IP and global anomaly limits
Phishing and real-time relay Proxies your login page and relays codes Passkeys (origin-bound), notifications, risk on new devices
MFA fatigue Floods push approvals Number matching, push rate limits, alert on denied pushes
Account enumeration Learns which emails have accounts Identical responses and timing on login, signup, and reset
Session theft Steals cookies or tokens via malware or XSS HttpOnly cookies, short tokens, DPoP, device binding, session list
Recovery abuse Targets reset and support flows Chapter 12 layers, waiting periods, notifications
SIM swap Takes over the phone number SMS as fallback only, never sole factor for recovery
Denial via lockout Locks real users out on purpose Progressive delays instead of hard lockouts

Rate limiting that does not lock out real users

Apply limits on several keys at once, with different windows:

Key Example policy
Per account Progressive delay after 5 failures; risk challenge after 10; ceiling well under NIST's 100
Per IP or subnet Burst limit per minute; stricter for hosting providers and anonymizers
Per device fingerprint Burst limit per minute
Global Alert when failure rate across all accounts jumps; this is how you spot stuffing
Per destination Limit codes and links sent to any one email or phone

Use a sliding-window counter in your session cache, keyed by hashed identifiers. Return the same generic error to the client whatever limit was hit.

Risk scoring

Score every sign-in on device familiarity, network reputation, geovelocity, credential breach status, and behavior. Map scores to actions: allow, step-up with a phishing-resistant factor, or block and notify. Log every score and its inputs so you can tune thresholds against real fraud.

Enumeration resistance

  • Same message for "no such account" and "wrong password."
  • Same response for reset requests whether or not the account exists.
  • Equal timing: run a dummy hash verification when the account does not exist so response time does not leak it.
  • Signup: handle existing accounts by email, not on-screen (Chapter 12).

Web security basics on auth pages

  • A strict Content Security Policy with no inline scripts on login pages.
  • frame-ancestors 'none' to block clickjacking.
  • CSRF tokens on every state-changing form, in addition to SameSite cookies.
  • No third-party scripts (analytics, chat widgets, tag managers) on authentication pages. Each one is a script that can read what users type.
  • HSTS with preload on your auth domain.

Notifications

Email the user on new device sign-in, password change, factor added or removed, email change, and recovery started. Each notification includes a "this was not me" link that freezes the account and starts recovery. Users become your detection system.

Warning

Common mistakes

  • Hard lockouts after 3 to 5 failures, which attackers use to lock out real users.
  • Rate limits only per IP, which botnets spread across thousands of addresses.
  • Analytics or marketing scripts on the login page.

Key takeaways

  • Defend in layers: breach checks, risk scoring, bot defense, and passkeys, each assumed to fail sometimes.
  • Rate-limit per account, IP, device, destination, and globally; global failure spikes reveal stuffing.
  • Make responses and timing identical for existing and non-existing accounts.
  • Keep third-party scripts off authentication pages entirely.