OIDC_MISSING_STATE security auth_error ai_generated true

OIDC authorization request missing state parameter allows CSRF attack on callback

ID: security/oidc-state-parameter-missing-allows-csrf

Also available as: JSON · Markdown · 中文
95%Fix Rate
90%Confidence
1Evidence
2023-11-05First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
OpenID Connect Core 1.0 active
Keycloak 22.0.0 active
Auth0 React SDK 2.0.0 active
oidc-client-ts 2.4.0 active
Spring Security OAuth2 Client 6.1.0 active

Root Cause

OpenID Connect authorization request does not include a cryptographically random 'state' parameter, enabling an attacker to inject an authorization code from their own session into the victim's callback, linking the victim's account to the attacker's identity.

generic

中文

OpenID Connect 授权请求未包含加密随机的 'state' 参数,使攻击者能够将其自己会话中的授权代码注入受害者的回调,将受害者的帐户与攻击者的身份关联起来。

Official Documentation

https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest

Workarounds

  1. 98% success Generate a cryptographically random state value for each authorization request and validate it in the callback. Example in Node.js using crypto: `const state = crypto.randomBytes(16).toString('hex'); session.state = state; res.redirect(`https://auth.example.com/authorize?state=${state}&...`);` and on callback: `if (req.query.state !== session.state) { reject('CSRF detected'); }`.
    Generate a cryptographically random state value for each authorization request and validate it in the callback. Example in Node.js using crypto: `const state = crypto.randomBytes(16).toString('hex'); session.state = state; res.redirect(`https://auth.example.com/authorize?state=${state}&...`);` and on callback: `if (req.query.state !== session.state) { reject('CSRF detected'); }`.
  2. 95% success Use a high-quality OIDC library that automatically handles state generation and validation (e.g., `openid-client` in Node.js or `oidc-client-ts` in JavaScript).
    Use a high-quality OIDC library that automatically handles state generation and validation (e.g., `openid-client` in Node.js or `oidc-client-ts` in JavaScript).

中文步骤

  1. Generate a cryptographically random state value for each authorization request and validate it in the callback. Example in Node.js using crypto: `const state = crypto.randomBytes(16).toString('hex'); session.state = state; res.redirect(`https://auth.example.com/authorize?state=${state}&...`);` and on callback: `if (req.query.state !== session.state) { reject('CSRF detected'); }`.
  2. Use a high-quality OIDC library that automatically handles state generation and validation (e.g., `openid-client` in Node.js or `oidc-client-ts` in JavaScript).

Dead Ends

Common approaches that don't work:

  1. 99% fail

    A static state is predictable and can be reused by an attacker; it provides no CSRF protection.

  2. 85% fail

    Nonce is verified in the ID token, but the authorization code exchange may occur before ID token validation; state is the primary CSRF defense for the code flow.

  3. 90% fail

    Redirect URI binding does not prevent code injection; an attacker can still intercept the callback if the redirect URI is open to manipulation.