All articles

BLOG / WHAT IS A REPLAY ATTACK

Replay Attacks Explained: Examples and Prevention

See how replay attacks reuse valid requests, why token expiry is not enough, and how nonces, one-use proof, and idempotency address different risks.

A request path and a returning duplicate loop meet a one-use state marker.A request path and a returning duplicate loop meet a one-use state marker.

A replay attack reuses a previously valid message, request, or proof to obtain an effect again. The attacker does not necessarily change the message or break its encryption. The failure occurs when the receiver accepts old authority without establishing that it is fresh, intended for this context, and still eligible for use.

For a web application, the consequence might be a repeated privileged action or reuse of captured authorization. An ordinary retry after a network interruption can look similar at the transport layer. Your server needs an explicit rule for each: reject reused authority, but safely recover the outcome of a legitimate operation.

How a replay attack works

  1. A legitimate interaction produces a request or proof with authority to do something.

  2. An attacker obtains a usable copy through a compromised client, leaked data, or another exposure.

  3. The attacker presents the copy again, potentially concurrently.

  4. The receiver checks authenticity but fails to check whether the authority is still valid for this use.

Preventing capture and preventing reuse are separate tasks. TLS protects a connection in transit; it does not by itself make application messages single-use after they reach an endpoint. A signature can establish that a message has not changed without establishing that it has never been accepted before.

NIST's authentication guidance on replay resistance distinguishes fresh authentication from replaying an earlier message. Its scope is authentication; the broader application examples below are design illustrations, not claims of NIST certification.

Authenticity, freshness, one-time consumption and idempotency answer different questions. None substitutes for all the others. Authenticity: Is the message genuine and unchanged?; Freshness: Is its authority still recent enough?; One-time use: Has this authority already been consumed?; Idempotency: Has the business operation already run?Authenticity, freshness, one-time consumption and idempotency answer different questions. None substitutes for all the others. Authenticity: Is the message genuine and unchanged?; Freshness: Is its authority still recent enough?; One-time use: Has this authority already been consumed?; Idempotency: Has the business operation already run?

Where replay risk appears in web applications

A short-lived assertion can be dangerous if another party can reuse it during its validity window. A checkout authorization can be authentic but wrong for the current order. A webhook can have a valid signature yet describe an event the application has already processed.

Review the effect attached to each message. Ask which account, session, operation, and destination it is meant for. Check whether a copied message remains useful after the original request has completed, and whether two application instances can accept it simultaneously.

Four controls with different jobs

Control Question it answers Important limitation
Integrity and authenticity Is this message genuine and unchanged? A genuine message can still be reused.
Freshness Is this authority recent enough? Expiry alone permits reuse inside the window.
One-time consumption Has this authority already been used? Separate check and update operations can race.
Idempotency Has this business operation already produced an outcome? It does not establish the caller's permission.

Context binding ties authority to the intended use: the relevant session and operation, for example. The exact context depends on the protocol. Do not invent cryptographic formats when a maintained protocol or provider-supported verification method already covers your use case.

Worked example: one order, two arriving requests

Illustrative design example: a customer submits an order and their connection drops before the response arrives. They retry. At almost the same moment, a captured copy of the first request arrives at another application instance.

Keep two decisions separate. First, establish that the requester is authorized and the request's proof is suitable for this use. Second, reconcile the order operation with the stored business outcome. If an order already exists for that customer's operation identifier and matching parameters, a legitimate retry may retrieve its existing result. Reused proof should not grant fresh authority to create a different order.

The database boundary matters. A sequence that reads “unused,” performs the action, and later writes “used” can allow concurrent requests to pass the first read. Consume one-use authority atomically, and enforce business uniqueness where the effect is committed. If a downstream service is involved, define how recovery works after a timeout rather than guessing that a missing response means failure.

For API v1, Stripe documents stored responses for idempotent requests: retries with the same key return the saved response after execution begins, and mismatched parameters are rejected. API v2 uses different retry semantics, so check the documentation for the API you use. Idempotency does not substitute for authentication or authorization.

Synthetic example: a lost response, a retry, and a concurrent copy

This is an application design example, not runnable SDK code, a tested implementation, or a customer result. Suppose an authenticated customer submits an order using operation key K and single-use proof P. The application scopes K to that customer and operation, records a canonical payload digest, and authorizes the requested purchase independently of browser verification. A key is a correlation identifier, not an authentication credential.

Two requests arrive together. The verifier must atomically check and consume P in its own authority store: checking first and marking later would let both requests pass. Separately, the application must atomically reserve K so only one worker can create the order. These are different state transitions. Consuming proof does not mean an order committed, and an operation reservation does not mean payment succeeded.

If the order commits but the response is lost, the customer can query authenticated operation status or retry under the application's documented recovery contract. An exact retransmission containing consumed P can still fail replay validation; idempotency does not make stale proof valid. A retry using fresh valid proof and the same K and payload can return the stored result after current authentication and authorization checks. Reusing K with a different payload must fail rather than silently returning another purchase's result.

If processing is still pending, return a documented pending result or status location rather than starting another purchase. If a crash occurs after proof consumption but before order commit, recover from durable operation state; do not clear the replay marker merely to make the retry pass. For an external payment side effect, carry a stable provider idempotency identifier and reconcile uncertain provider status. A database transaction alone cannot make a remote payment and local order commit atomic.

Set and document retention for both replay markers and operation records. Expiry must not silently turn an old purchase into a new charge: require an explicit new operation or reconciliation when the original result can no longer be recovered. These are design requirements to validate in your stack, not guarantees supplied by the HTTP method. RFC 9110 section 9.2.2 defines method idempotency and cautions about automatic retries of non-idempotent requests.

Signed webhooks need freshness and duplicate handling

Use the provider's supported signature verification on the expected raw message, with its documented timestamp checks. Then reconcile the event with your application's recorded processing state. Do not assume that every repeated delivery is hostile: providers can retry when acknowledgments are missing.

Stripe documents timestamp-based replay protection and duplicate event handling as distinct concerns. Preserve that distinction in your design. A recent delivery can still describe an event already applied to your order, subscription, or account.

A focused replay review

  • List the messages that grant authority and the effects they can trigger.

  • Check expiry, intended context, and reuse behavior independently.

  • Test two simultaneous submissions against different instances in an authorized test environment.

  • Confirm a legitimate retry cannot create a second business effect.

  • Test changed parameters with the same operation identifier.

  • Test recovery after a downstream success with a lost response.

  • Define retention, unavailable-state behavior, and an operator recovery path.

Record expected results before running the tests. “The second request failed” is incomplete evidence if the first request created two effects, or if a customer cannot recover their successful order.

Where MANDATE fits

MANDATE's browser-verification approach uses opaque proof and hosted decisions that consult live server-side state. The design addresses browser proof reuse in the context of high-value actions. The application still owns order uniqueness, payment authorization, and recovery of completed work.

Read retries, replay, and business outcomes for that separation, or anti-bot verification for the browser integration perspective. Start with one valuable action and prove its retry behavior before extending the policy.

AI-assisted editorial revision. References checked for this revision.

Put the distinction into practice: Use the tested idempotency-key example to examine retry behavior, then review the SAML assertion replay checklist if the repeated message is an authentication handoff. Those protocols have different acceptance rules; a browser-action check does not replace SAML validation.

More from the blog

BOT ATTACKS

Bot Attacks: A Complete Guide for Developers

Learn what bot attacks are, how to detect automated abuse, and practical mitigation strategies that protect signups and checkouts without CAPTCHAs.

SAML REPLAY ATTACK

SAML Replay Attack Prevention: Stopping Reused Assertions

SAML replay attack prevention explained: how signed assertions get reused, which checks stop them, and how to roll out one-time-use tracking safely.

ONLINE BUYING BOT

Online Buying Bot Playbook: Defenses Without CAPTCHAs

See how buying bots target stock, tickets, and checkout. Compare purchase limits, browser proof, and safe retries without adding CAPTCHA puzzles.