📋 What Is It?
Broken User Authentication covers every way an API fails to establish, protect, or invalidate the caller's identity. Authentication in APIs is harder than in classic web apps: there is no browser session to lean on, credentials and tokens travel in headers on every request, and endpoints such as /login, /register, /token/refresh and /password/reset are publicly reachable by design - so they are attacked directly, at machine speed, with no rate limit from a human clicking a form.
Once authentication breaks, every other control downstream is decorative: the attacker is a legitimate user as far as the system is concerned.
⚠️ Common Exploits
- Credential Stuffing: breached password lists replayed against
/loginwith no throttle - Brute Force: unlimited attempts on passwords, PINs, and OTPs
- alg:none / Weak Secret JWT: tokens forged because the signature is not properly verified
- Token in URL: access tokens in query strings leak via logs, referrers, and history
- No Expiry / No Revocation: a stolen token is valid forever
- Weak Password Reset: guessable tokens, no expiry, reusable links
- API Key as Identity: a single shared key treated as proof of a user
🔴 Attack Flow
↓
2. Probe for rate limiting, lockout, and user enumeration in responses
↓
3. Stuff credentials / brute-force OTPs at high volume
↓
4. Or capture a token and test
alg:none, weak secrets, missing expiry↓
5. IMPACT: Full account takeover - and the logs show a "valid" login!
❌ Vulnerable Code
✅ Secure Code
✓ Prevention Checklist
- Inventory every authentication flow, including refresh and reset
- Use a proven identity provider rather than hand-rolled auth
- Hash passwords with Argon2id/bcrypt/scrypt; never encrypt or store plaintext
- Verify JWTs with a pinned algorithm, issuer, audience, and expiry
- Keep access tokens short-lived; rotate and allow revocation of refresh tokens
- Send tokens in headers - never in URLs or query strings
- Rate-limit and lock out per account and per source, including OTP endpoints
- Return identical responses for unknown user and wrong password
- Offer MFA and enforce it for privileged accounts
- Make reset tokens random, hashed at rest, single-use, and short-lived
- Re-authenticate before sensitive changes (email, password, payout details)
- Log authentication events and alert on credential-stuffing patterns
🔍 Detection & Tools
Identity & Libraries:
Testing:
How to Test:
- Send 100 bad logins - is there any throttle or lockout?
- Compare responses for unknown user vs wrong password
- Re-sign a token with
alg:noneand with a guessed HMAC secret - Strip or extend
exp; check the token is rejected - Reuse a password-reset link twice, and after an hour
- Log out, then replay the old token - is it revoked?
🌍 Real-World
These are documented incident classes - recurring patterns rather than single CVEs.
- Credential stuffing at scale: unthrottled mobile login APIs let attackers replay breached password lists until thousands of accounts open.
- OTP brute force: a 4–6 digit code with no attempt limit is exhausted in minutes, defeating "MFA" entirely.
- Forged JWTs: services that decode instead of verify, or accept
alg:none, hand admin access to anyone who edits a claim. - Tokens leaked in URLs: access tokens in query strings end up in proxy logs, analytics, and browser history, then get replayed.
- Never-expiring sessions: tokens with no expiry or revocation stay usable long after a device is lost or an employee leaves.
📌 Quick Tips
- DO NOT use
jwt.decode()as an auth check - DO NOT reveal whether an account exists
- DO NOT put tokens in URLs
- DO pin the algorithm and validate iss/aud/exp
- DO throttle every auth endpoint, OTP included
- DO re-authenticate before sensitive changes
📜 Compliance
Related Standards:
- OWASP API Security Top 10 2019 - API2
- Maps to API2:2023 Broken Authentication
- CWE-287 Improper Authentication
- CWE-307 Improper Restriction of Excessive Authentication Attempts
- CWE-345 Insufficient Verification of Data Authenticity
- NIST SP 800-63B Digital Identity Guidelines