An API replay attack reuses previously valid API material—such as a signed request, bearer token, JWT, webhook, authorization message, or transaction—so the server accepts it again. The key weakness is not necessarily broken cryptography. It is a missing check for freshness, uniqueness, sender binding, or one-time business intent.
jti, server-side duplicate detection, sufficient cryptographic binding to the request, correct authorization, and idempotency or one-time state for operations that must not execute twice.NIST defines replay attacks as replaying previously captured messages to masquerade as a legitimate claimant or verifier, and defines replay resistance as protection against captured authentication or access-control information being retransmitted for an unauthorized effect. The same security property applies naturally to APIs that carry signed HTTP messages, bearer tokens, webhooks, and state-changing business operations.
What Is an API Replay Attack?
Replay is different from request forgery. In a forgery, the attacker changes or creates material and tries to make it look legitimate. In a replay, the attacker often keeps the trusted material intact and exploits the server's willingness to accept it again.
| Pattern | What the attacker reuses or abuses | Primary defense question |
|---|---|---|
| Exact replay | Previously valid request, proof, token, or event | Has this proof expired or already been accepted? |
| Bearer-token replay | A stolen access token | Is the token constrained to the intended sender and audience? |
| Webhook replay | A valid signed delivery | Is the signature fresh and the delivery/event ID new? |
| Business-action replay | Same payment, refund, approval, or workflow intent | Should the business effect be allowed to happen twice? |
How Does a Replay Attack Work?
The mechanics vary, but the sequence is usually simple: obtain valid material, preserve what makes it acceptable, resend it, and rely on the verifier checking authenticity without checking enough freshness or prior use.
1. Obtain valid material
The material may come from a compromised client, leaked logs, malware, an exposed token, a copied webhook, a malicious endpoint, or another system that legitimately received the credential or message.
2. Preserve its trusted fields
The attacker keeps the token, signature, body, headers, target, or proof fields sufficiently intact for verification to succeed.
3. Submit it again
The same message may be replayed immediately, inside a freshness window, from another host, or against a different resource server if the proof is not properly scoped.
4. Exploit missing replay state
The server verifies that the proof is valid but does not recognize that the nonce, proof ID, event ID, token, or business operation was already used.
RFC 9421 explicitly describes signature replay. It recommends signing enough message components to distinguish one request from another, and supports a single-use nonce plus created and expires signature parameters to limit reuse.
Replay timeline
T0 Client sends a valid POST /payments
signature = valid
timestamp = fresh
nonce = abc123
T1 Server accepts the payment
T2 Captured request is sent again
Vulnerable verifier asks:
signature valid? yes
token valid? yes
Replay-resistant verifier also asks:
timestamp still acceptable?
nonce or proof ID already seen?
token bound to this sender and audience?
business operation already completed?Replay Attack vs Legitimate Retry vs Idempotency
Repeated requests are not automatically malicious. Mobile clients retry after timeouts, webhook providers redeliver, and payment SDKs may resend when they cannot tell whether the first request completed. Replay protection therefore has to preserve safe retry behavior.
| Repeated request | Typical intent | Safe handling |
|---|---|---|
| Transport retry | Client is unsure whether the first call succeeded | Use idempotency or transaction state to return the safe result without repeating the effect. |
| Webhook redelivery | Provider intentionally retries an unacknowledged event | Reverify the delivery and deduplicate using the provider's event or delivery semantics. |
| Exact proof replay | Attacker reuses the same proof or signed request | Reject expired or already-seen nonce, jti, proof ID, or signed message. |
| Replay-like business abuse | Attacker repeats harmful intent using new valid proofs | Use authorization, idempotency, workflow state, rate controls, and runtime behavior detection. |
Idempotency is not the same as replay resistance. Idempotency controls the business effect of retrying a state-changing operation. It does not by itself authenticate the caller or prove that a security proof is fresh. Stripe's API illustrates the difference: an idempotency key allows safe retries, while webhook and authentication controls address different security properties.
What Changed or Matters in 2026?
Replay resistance itself is not new, but the API-security guidance around it continues to mature. NIST's updated SP 800-228, updated March 13, 2026, adds API risks and recommended controls organized by API lifecycle stage. NIST also published the initial public draft of SP 800-228A in May 2026 with deployment guidance specifically for RESTful Web APIs. SP 800-228A is a draft, not a final standard.
For OAuth, the current security Best Current Practice is RFC 9700 (January 2025). It has a dedicated token replay prevention section and recommends sender-constrained access tokens such as mutual TLS or DPoP. For public-client refresh tokens, it requires sender constraint or refresh-token rotation.
Core API Replay Attack Prevention Controls
Replay resistance is strongest when each layer owns a clear part of the problem instead of forcing everything into one gateway rule or one application library.
| Layer | Responsibility | Examples |
|---|---|---|
| Transport | Protect credentials and message content in transit | TLS / HTTPS, mTLS |
| Identity / authorization | Reduce usefulness of stolen tokens | Short lifetimes, audience restriction, DPoP, certificate-bound tokens, refresh-token rotation |
| Request verification | Verify freshness and request binding | HTTP Message Signatures, HMAC schemes, signed timestamps, nonces |
| Replay state | Remember recently accepted identifiers | Nonce cache, proof-ID cache, event/delivery deduplication |
| Business application | Prevent duplicate business effects | Idempotency keys, transaction IDs, spent-token state, workflow state |
| Runtime security / SOC | Detect repeated intent and investigate abuse | Behavior analytics, request/response context, SIEM evidence |
Use TLS, but do not confuse encryption with replay resistance
HTTPS is foundational because it protects traffic in transit. It does not automatically make an application message single-use if valid material is obtained elsewhere. RFC 9421 explicitly treats TLS and HTTP message signatures as complementary controls.
Use a short freshness window
Signed creation and expiration times limit how long captured material remains useful. AWS Signature Version 4 provides a concrete operational example: AWS states that, in most cases, a signed request must reach AWS within five minutes of the request timestamp or it is denied. Your own window should be based on protocol behavior, clock accuracy, network conditions, and business risk—not copied blindly from another platform.
Use unique, verifiable identifiers
A nonce, proof ID, request ID, jti, event ID, or delivery ID only helps if the verifier can detect reuse during the relevant validity period. Distributed systems must keep this replay state consistent enough across replicas to prevent one server from accepting an identifier another server has already seen.
Bind the proof to the actual request
A signature that covers too little can be replayed in another meaningful context. Bind the proof to the method, target URI, relevant headers, body digest, freshness data, and authorization context required by your protocol. RFC 9421 specifically warns that insufficient component coverage can enable valid signatures to be reused on different messages.
Use sender-constrained OAuth tokens for high-value APIs
RFC 9700 recommends DPoP or mutual TLS to reduce misuse of stolen or leaked access tokens. Sender constraint changes the security model: possession of the token alone is no longer enough; the caller must also prove possession of the corresponding key material.
Keep one-time operations one time
Password resets, authorization-code redemption, enrollment challenges, approvals, and similar workflows require state that marks successful use. A cryptographically valid artifact can still be logically spent.
A Practical Replay-Resistant REST API Pattern
POST /v1/payments Authorization: sender-constrained access token X-Request-Timestamp: 2026-09-16T09:42:17Z X-Request-Nonce: unique-random-value Idempotency-Key: payment-attempt-7d91... Signature-Input: method + path + timestamp + nonce + body-digest Signature: cryptographic proof over required components Server-side validation order 1. Require HTTPS. 2. Authenticate the caller. 3. Verify the signature or proof and required component coverage. 4. Check timestamp / created / expires freshness. 5. Reject a nonce or proof ID that has already been accepted. 6. Verify token audience and sender binding when used. 7. Apply authorization and business rules. 8. Apply idempotency or one-time state for the business operation. 9. Process the request. 10. Record replay-relevant evidence without logging secrets.
OAuth, JWT, DPoP, and mTLS Replay Protection
Bearer tokens are replayable if stolen
Bearer tokens intentionally make possession sufficient for use. RFC 9700 therefore recommends audience restriction and sender-constrained tokens for cases where access-token replay is a meaningful risk.
JWT jti can support replay detection
RFC 7519 defines jti as a unique JWT identifier and notes that it can be used to prevent replay. The claim does not create replay protection by itself; the receiver must enforce uniqueness or another policy that makes repeated use unacceptable.
DPoP binds the token to a key and the proof to a request
RFC 9449 requires DPoP proofs to contain a unique jti, the HTTP method (htm), target URI (htu), and issue time (iat); protected-resource proofs also bind to the access token using ath. Servers can retain proof identifiers for the acceptance window and reject reuse. DPoP can also use a server-provided nonce when stronger freshness control is needed.
mTLS certificate-bound tokens reduce stolen-token reuse
RFC 8705 binds an OAuth access token to the client's certificate so a resource server can require proof of possession of the corresponding private key. This reduces the value of a stolen token to a party that does not possess that key.
Refresh-token rotation helps reveal replay
RFC 9700 requires public-client refresh tokens to be sender-constrained or rotated. With rotation, reuse of an invalidated refresh token can reveal that the token was copied and used by more than one party.
Webhook Replay Protection
Webhook security needs both authenticity and delivery semantics. Verify the provider's signature first, then apply freshness and deduplication rules supported by that provider.
Stripe
Stripe signs a timestamp inside the Stripe-Signature material and documents a default five-minute tolerance in its libraries. It also generates a new signature and timestamp for each retry. That means receivers should validate the current signature and still use event/business identifiers where they need idempotent processing.
GitHub
GitHub recommends validating X-Hub-Signature-256 and using X-GitHub-Delivery to ensure delivery uniqueness. A requested redelivery keeps the same delivery identifier, which makes deduplication semantics explicit.
How to Test Replay Resistance Safely
Replay testing should be performed only in systems you are authorized to test, preferably in a staging or isolated environment with synthetic data and clear stop conditions.
- Send one known-safe state-changing request and record the expected result.
- Repeat the exact request inside the normal acceptance window.
- Confirm the application either rejects the reused proof or returns the original idempotent result without repeating the business effect.
- Repeat after the freshness window and confirm the proof is rejected.
- For DPoP or nonce-based designs, confirm reuse of the same proof identifier is rejected according to the system's policy.
- Verify behavior across replicas or regions so duplicate tracking is not local to only one server.
- Confirm logs contain identifiers useful for investigation without storing bearer tokens, private keys, raw secrets, or unnecessary sensitive payloads.
Runtime Detection: Where Ammune Fits
Protocol-level replay prevention belongs in the API, gateway, authorization server, or identity layer. Runtime security complements those controls by looking for suspicious repeated intent when the attacker changes the outer request, obtains new credentials, regenerates signatures, or otherwise avoids an exact byte-for-byte duplicate.
Ammune can support that monitoring layer by analyzing live API requests and responses, API behavior, repeated actions or sequences, sensitive-data context, and security events that can be forwarded into SIEM and incident-response workflows. This should complement—not replace—nonces, freshness checks, sender-constrained tokens, replay caches, authorization, and idempotency.
| Signal | Why it matters | Useful evidence |
|---|---|---|
| Repeated high-value action | May indicate exact replay or repeated business intent | Endpoint, method, principal, transaction/event ID, result |
| Same proof identifier | Strong indicator when the identifier is meant to be single-use | Nonce, jti, DPoP proof ID, webhook delivery ID |
| Same token from changing contexts | Can indicate credential theft or replay | Token subject, audience, client identity, network/device context |
| Repeated action with fresh proofs | Exact replay controls may pass while business abuse continues | Sequence, object IDs, rate, response data, user/session correlation |
Related Ammune guidance: API runtime security protection, business-logic abuse detection, rate limiting versus behavior detection, and SIEM log forwarding formats.
Incident Response for Suspected Replay Activity
- Confirm the repeated effect. Determine whether the system executed the same operation twice or merely received a safe retry.
- Identify the reused trust material. Correlate request IDs, nonce/proof IDs, token subject and audience,
jti, webhook delivery ID, idempotency key, and transaction identifiers. - Contain credentials where necessary. Revoke or rotate compromised tokens, keys, sessions, or webhook secrets according to the affected protocol.
- Close the protocol gap. Add or tighten freshness, replay state, sender constraint, audience restriction, or one-time semantics.
- Protect the business workflow. Add idempotency or transaction-state checks where repeated execution is unsafe.
- Hunt for related activity. Search for the same principal, proof identifiers, endpoints, objects, or transaction patterns across the relevant time window.
For broader investigation workflow, see the API security incident response playbook.
Common Replay-Prevention Mistakes
Timestamp only
A timestamp limits replay time but can still allow repeated use inside the accepted window.
Nonce without storage
A unique value does not prevent reuse unless the verifier can recognize that it has already been accepted.
Local replay cache only
Multi-node systems can accept the same proof on different replicas if replay state is not shared appropriately.
Signing too little
If method, target, body, or important context is not covered, a valid signature may remain portable to another request.
Long-lived bearer tokens
A long token lifetime increases the opportunity to reuse a stolen token when no sender constraint exists.
Logging secrets for forensics
Investigation requires correlation identifiers—not raw bearer tokens, private keys, or unnecessary sensitive payloads.
API Replay Attack Prevention Checklist
- Use HTTPS for all protected API traffic.
- Define what must be fresh and what must be unique for every high-value operation.
- Use a signed timestamp or equivalent creation/expiration semantics.
- Use a nonce, proof ID, request ID,
jti, event ID, or equivalent where single use is required. - Retain replay state for the complete proof-validity window.
- Make replay state work across the actual cluster, region, or gateway topology.
- Cryptographically bind the proof to enough request context.
- Use audience restriction and sender-constrained OAuth tokens for high-value cases where practical.
- Rotate or sender-constrain public-client refresh tokens.
- Use idempotency or transaction state for retryable state changes.
- Verify webhook signatures and provider-specific delivery/freshness semantics.
- Keep one-time workflows stateful enough to invalidate spent artifacts.
- Test exact replay, retry behavior, expiration, and cross-replica handling in an authorized environment.
- Log correlation identifiers without logging reusable secrets.
- Use runtime detection for replay-like behavior that exact cryptographic controls cannot see.
Primary References
- NIST CSRC — Replay attack
- NIST CSRC — Replay resistance
- NIST SP 800-228 — Guidelines for API Protection for Cloud-Native Systems, updated March 2026
- NIST SP 800-228A — RESTful Web API secure deployment, initial public draft, May 2026
- RFC 9421 — HTTP Message Signatures
- RFC 9700 — Best Current Practice for OAuth 2.0 Security
- RFC 9449 — OAuth 2.0 Demonstrating Proof of Possession (DPoP)
- RFC 8705 — OAuth 2.0 mTLS and certificate-bound access tokens
- RFC 7519 — JSON Web Token (JWT)
- Stripe — Webhook signature and replay guidance
- GitHub — Webhook best practices
- AWS — Signature Version 4
Frequently Asked Questions
What is an API replay attack?
It is the reuse of previously valid API material so the server accepts it again. The reused material may be a signed request, token, JWT, webhook, authorization message, or business transaction.
Do timestamps alone prevent replay attacks?
No. They reduce the useful lifetime of captured material, but the same proof can still be reused inside the accepted window unless the server also detects reuse or the protocol has equivalent single-use semantics.
How do nonces prevent replay?
A nonce creates a per-message unique value. Replay resistance requires the nonce to be protected appropriately and the verifier to remember accepted values for the relevant validity window so duplicates can be rejected.
Can JWTs be replayed?
Yes. A valid JWT can normally be reused until it expires unless the application adds sender binding, one-time state, or another replay policy. RFC 7519 notes that the jti claim can be used for replay prevention, but the receiver has to enforce it.
How do DPoP and mTLS reduce token replay?
They sender-constrain OAuth tokens so possession of the token alone is insufficient. DPoP requires a request-specific proof from a private key; mTLS certificate-bound tokens require proof of possession of the key corresponding to the bound client certificate.
Is idempotency the same as replay protection?
No. Idempotency prevents duplicate business effects during safe retries. Replay protection determines whether a security proof or request should still be trusted. High-value APIs often need both.
How should webhook replay be handled?
Verify the provider signature, apply the provider's freshness rules, and deduplicate using stable event or delivery identifiers when the provider supplies them.
Where does Ammune fit?
Ammune can complement protocol controls with runtime visibility into repeated actions, sequences, request/response context, business behavior, and SIEM-ready evidence. It does not replace nonces, request signatures, sender-constrained tokens, replay caches, or idempotency.
Strengthen Replay Protection with Runtime API Visibility
Protocol controls should reject stale or reused proofs. Runtime API security adds context for repeated intent, abnormal sequences, credential misuse, and business-logic abuse that may use fresh outer requests.
