1001Ferramentas
🛡️Generators

OAuth State CSRF Token

Gera valor "state" criptograficamente aleatório (32 bytes base64url) para mitigar CSRF.

state

OAuth state parameter: CSRF protection in authorization code flow

The state parameter is the canonical defense against CSRF (Cross-Site Request Forgery) in the OAuth 2.0 Authorization Code flow. RFC 6749 §10.12 recommends it; OAuth 2.1 keeps it alongside the now-mandatory PKCE. Without state, a malicious site could trick a logged-in victim's browser into completing an authorization callback under the attacker's account — and the victim's app would attach the resulting tokens to the wrong session.

The mechanism is simple: before redirecting to the authorization endpoint, the client generates a cryptographically random string, stores it server-side bound to the user session, and sends it in the state query parameter. When the authorization server redirects back with the code, it includes the same state verbatim. The client compares the received state to the stored one — a mismatch aborts the flow.

Generation and verification

Use a CSPRNG — never Math.random(). Minimum entropy: 128 bits (16 bytes); 256 bits (32 bytes) is safer:

// Node
const state = crypto.randomBytes(32).toString('base64url');
req.session.oauthState = state;
res.redirect(`https://idp.example.com/authorize?state=${state}&...`);

// callback
if (req.query.state !== req.session.oauthState) {
  return res.status(400).send('CSRF detected');
}
delete req.session.oauthState; // single-use

Encode as base64url to avoid URL-encoding traps. Make the value single-use (delete after verification) and short-lived (5–10 min TTL).

State vs PKCE — both, not either

PKCE (RFC 7636) prevents authorization code interception on public clients; state prevents CSRF on the callback URL. They mitigate different attacks. OAuth 2.1 mandates PKCE for all clients but still recommends state. Major SDKs (Passport.js, NextAuth, Auth0, Spring Security, Authlib) generate and verify state automatically — but verify in tests that your handler actually compares it.

Encoding a return path inside state

It is common to also carry a "return URL" through state — e.g. { csrf: "", returnTo: "/dashboard" } JSON, base64url-encoded. Always sign or HMAC the payload (the client controls what comes back). Never trust a raw return URL — validate it is same-origin to prevent open redirect.

FAQ

How long should the state be? 128 bits minimum (16 random bytes ≈ 22 base64url chars); 256 bits (32 bytes ≈ 43 chars) is the modern default. Shorter values can be brute-forced offline.

Can I reuse the same state across users? No. State must be per-flow and bound to the user's session — reuse breaks the CSRF guarantee.

Is state still needed with SameSite cookies? Yes. SameSite=Lax mitigates most CSRF, but the OAuth callback is a top-level navigation that does send Lax cookies — so state remains the explicit, framework-agnostic defense.

What if the SDK already handles state? Verify it does — write an integration test that tampers with the callback and expects rejection. Silent failure of state checks has caused real CVEs.

Related Tools