OAuth state parameter validated on callback
Why it matters
OAuth without state parameter validation (CWE-352, CWE-601) is a CSRF attack on the OAuth flow itself. An attacker who tricks a victim into visiting a crafted URL can complete an OAuth authorization as the attacker, binding their identity to the victim's account — a classic account takeover vector. OWASP A01 (Broken Access Control) and NIST 800-53 IA-8 both require integrity checks on authentication callbacks. The state parameter is the mechanism: it must be a cryptographically random value generated by the application and stored server-side (not just echoed back) so the callback can verify the request originated from the expected user.
Severity rationale
Medium because exploitation requires luring the victim to a crafted URL, but a successful attack results in account takeover by linking an attacker-controlled OAuth identity.
Remediation
Generate a random state, store it in an httpOnly cookie, and validate it in the callback before exchanging the authorization code:
// Before redirecting to provider:
const state = crypto.randomUUID()
cookies().set('oauth_state', state, { httpOnly: true, secure: true, maxAge: 600 })
redirect(`https://github.com/login/oauth/authorize?client_id=${CLIENT_ID}&state=${state}`)
// In the callback route:
const returnedState = searchParams.get('state')
const storedState = cookies().get('oauth_state')?.value
if (!returnedState || returnedState !== storedState) {
return Response.json({ error: 'Invalid state' }, { status: 400 })
}
cookies().delete('oauth_state')
// Proceed with code exchange
Do not compare state to a static value — it must be unique per authorization request and session-bound.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Security Hardening Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-352 — Cross-Site Request Forgery (CSRF)
- cwe · CWE-601 — URL Redirection to Untrusted Site
- owasp:2021 · A01 — Broken Access Control
- nist:rev5 · IA-8 — Identification and Authentication (Non-Organizational Users)
Taxons
History
- 2026-04-18·v1.0.0·Initial import from security-hardening·automated