Improper Authentication
Improper Authentication
What it is
CWE-287 covers a family of weaknesses where an application fails to correctly verify the identity of an entity (user, service, device) that interacts with it. Variants include missing authentication for critical functions, broken authentication logic, weak credentials, predictable session identifiers, and authentication bypass via parameter manipulation.
Why it matters
Improper authentication maps directly to account takeover, lateral movement, and total compromise. It is the foundational weakness behind most disclosed breaches. The OWASP Top 10 elevates Broken Access Control (A01) and Identification and Authentication Failures (A07) into the top tier for this reason. HIPAA, PCI-DSS, and CMMC all impose explicit authentication-control requirements that map to this CWE.
Common patterns
- •Authentication checks that only happen client-side (the API doesn't re-verify).
- •Password comparison via == (timing-attackable) instead of constant-time comparison.
- •Session IDs generated from predictable sources (timestamps, counters, weak PRNG).
- •Token validation that decodes JWTs but does not verify the signature.
- •Routes that check 'logged in' without checking 'authorized for this resource'.
- •Backdoor or debug routes left enabled in production.
Languages affected
What Deva detects
Deva includes a suite of authentication-specific rules: detection of password comparison without constant-time helpers (use crypto.timingSafeEqual, secrets.compare_digest), JWT verify calls with verify: false or with no signing key, missing requireAuth middleware before sensitive route handlers, session ID generation with Math.random or other weak sources, and hardcoded credentials in code or configs (CWE-798 overlap).
Example
Vulnerable
app.post('/transfer', async (req, res) => {
const { fromAccount, toAccount, amount } = req.body
await db.transfer(fromAccount, toAccount, amount)
res.json({ ok: true })
})Fixed
app.post('/transfer', requireAuth, async (req, res) => {
const { toAccount, amount } = req.body
const userId = req.user.id
const fromAccount = await db.getAccountForUser(userId)
if (!fromAccount) return res.status(403).json({ error: 'No account' })
await db.transfer(fromAccount.id, toAccount, amount)
res.json({ ok: true })
})Explanation
The vulnerable version has no authentication middleware and accepts fromAccount as a request parameter. Any caller can transfer from any account. The fix gates the route on requireAuth, derives the fromAccount from the authenticated user's identity rather than from request input, and confirms ownership before executing the transfer.
Where this fits in OWASP Top 10
Compliance framework mapping
| Framework | Controls |
|---|---|
| OWASP Top 10 (2021) | A01:2021 Broken Access ControlA07:2021 Identification and Authentication Failures |
| NIST 800-53 Rev 5 | IA-2 Identification and AuthenticationAC-3 Access Enforcement |
| PCI-DSS v4.0 | 8.3 Strong authentication |
| HIPAA Security Rule | 164.312(d) Person or Entity Authentication |
| CMMC 2.0 L2 | IA.L2-3.5.1 Identify users |
Related CWEs
Deva detects CWE-287 alongside 970+ other CWE patterns at write time, with AI-assisted fix generation that maintains compliance.