Skip to main content

Cross-site Request Forgery (CSRF) and Replay Attacks

Benefits

Protecting against CSRF and replay attacks provides:

  • Prevents Unauthorized Logins: Stops attackers from tricking users into logging into attacker-controlled accounts
  • Blocks Token Reuse: Prevents attackers from reusing captured authentication codes
  • Standards Compliance: Uses industry-standard OAuth 2.0 and OpenID Connect security mechanisms
  • Automatic Protection: Most OAuth/OIDC libraries handle this automatically
  • User Trust: Users can trust that their login sessions are secure

Overview

OAuth 2.0 and OpenID Connect (OIDC) are security standards that define how users can securely log into applications. However, these standards need to be implemented correctly to prevent attacks.

cidaas uses two special security parameters—state and nonce—that are built into OAuth 2.0 and OIDC to protect against common attacks.

What is OAuth 2.0?

OAuth 2.0 is a security standard that allows applications to access user data without getting the user's password. It's like giving a valet key to your car—the valet can drive it, but can't access the trunk or glove box.

OAuth 2.0's role in security:

  • Defines secure ways for apps to request access
  • Provides different "flows" (like Authorization Code, PKCE) for different app types
  • Uses tokens instead of passwords for access
  • Includes the state parameter to prevent CSRF attacks

What is OpenID Connect (OIDC)?

OpenID Connect (OIDC) builds on OAuth 2.0 and adds user identity information. While OAuth 2.0 is about "what can this app access?", OIDC answers "who is this user?"

OIDC's role in security:

  • Provides ID Tokens that prove user identity
  • Includes the nonce parameter to prevent replay attacks
  • Adds extra security checks beyond basic OAuth 2.0

OAuth 2.0 and OIDC Security Patterns

Different OAuth 2.0 flows provide different levels of security:

  1. Authorization Code Flow - Most secure for web apps with a backend server
  2. PKCE Flow - Adds extra security for mobile apps and single-page apps (prevents code interception)
  3. Client Credentials Flow - For server-to-server communication (no user involved)
  4. Device Code Flow - For devices without browsers (like smart TVs)

Each flow has specific security requirements. The Security Dashboard automatically checks if you're using the right flow for your app type.

State Parameter (OAuth 2.0)

The state parameter is part of the OAuth 2.0 standard. Think of it like a secret handshake:

  1. Your app creates a random secret code (state)
  2. You send it to cidaas when starting login
  3. cidaas sends it back after login
  4. Your app checks: "Is this the same code I sent?"

If the codes don't match, someone might be trying to trick you, so you reject the login. This prevents CSRF attacks.

Nonce Parameter (OpenID Connect)

The nonce parameter is part of OpenID Connect. It works similarly but protects against a different attack:

  1. Your app creates a random code (nonce)
  2. You send it to cidaas when starting login
  3. cidaas includes it in the ID Token
  4. Your app checks the ID Token: "Is this the same code I sent?"

This prevents attackers from reusing old authentication codes. This prevents replay attacks.

Understanding CSRF Attacks

Cross-site Request Forgery (CSRF) is like someone tricking you into signing a document you didn't read. In web security, an attacker tricks a user into logging in without realizing it.

Simple example:

  1. You're logged into your bank's website
  2. An attacker sends you a link (maybe in an email that looks legitimate)
  3. You click the link
  4. Without you knowing, the link makes you log into the attacker's account instead of yours
  5. Now any actions you take (like transferring money) happen in the attacker's account

CSRF

How the state parameter prevents this:

  • Your app creates a unique secret code before starting login
  • If an attacker tries to trick you, they won't have your secret code
  • Your app checks: "Do I recognize this code?" If not, it rejects the login
  • This ensures only legitimate login requests from your app are accepted

Understanding Replay Attacks

A replay attack is like someone recording your house key and making a copy. An attacker captures valid authentication data and tries to reuse it.

Simple example:

  1. You log into an app successfully
  2. An attacker intercepts the authentication code
  3. The attacker tries to use that same code again to log in as you
  4. Without protection, this could work

Replay-Attacks

How cidaas prevents this:

  • Authorization codes can only be used once—like a single-use ticket
  • If someone tries to reuse a code, cidaas automatically rejects it
  • The nonce parameter ensures ID Tokens are only valid for one specific login event
  • Even if an attacker captures a code, they can't use it again

Implementing state and nonce

The state and nonce parameters are sent as part of the authorization request (authz). This request initiates authentication and may involve redirects, single sign-on, or external identity providers.

Important

Always generate new and unique values for state, nonce, and code_challenge for every authorization request.

Authorization request parameters

ParameterDescription
client_idRepresents the client (application) registered in cidaas
redirect_uriURI where cidaas redirects the user after successful authentication
scopeRequested scopes (for example, openid, profile)
response_typeMust be code when using PKCE
code_challengeBase64 URL-encoded hash of the code_verifier
code_challenge_methodHashing method used (S256 recommended)
response_modeDefines how cidaas returns the response (form_post recommended)
stateOpaque value to prevent CSRF attacks
nonceString value to prevent replay attacks

State parameter implementation

Most OAuth 2.0 / OIDC libraries generate and validate state automatically. If implementing manually, follow these steps:

Generate the state

  • Use a secure random string generator
  • Follow the same character and length recommendations as for PKCE code_verifier
  • Recommended length: 43–128 characters
note

If the value is too long, the request may fail with HTTP 414 (URI Too Long).

Store the state

Store the generated value before redirecting the user. Common storage options include:

  • Secure cookies (recommended)
  • Application memory
  • Local storage (client-side apps)

If using cookies, configure with:

  • Secure and HttpOnly flags enabled
  • SameSite=None
  • Cookie path scoped to the redirect_uri
  • Reasonable expiration time (maxAge)

Validate the state

After redirection, perform validation:

  1. Extract state from the callback request
  2. Retrieve the previously stored value
  3. Compare both values
  4. Proceed with code exchange only if values match

Nonce parameter implementation

The nonce generation follows the same randomness and length recommendations as state.

Store the nonce

Unlike state, the nonce should not be stored in the user agent. Store it in:

  • Database
  • Server-side memory
  • Disk storage

Associate the value with a timestamp for expiration validation.

Validate the nonce

After successful authentication and code exchange:

  1. Decode the id_token
  2. Extract the nonce claim
  3. Retrieve the stored nonce
  4. Verify the value is not older than 10 minutes (recommended)
  5. Verify both nonce values match

If validation fails, trigger re-authentication using prompt=login.

State vs nonce

AspectStateNonce
Sent to cidaasQuery parameter stateQuery parameter nonce
Primary protectionCSRF attacksReplay attacks
Storage locationCookie, memory, or local storageDatabase, server memory, or disk
Retrieved fromRedirect requestID Token
Validation timingBefore code exchangeAfter ID Token decoding

warning

Need Support?

Please contact us directly on our support page.