Security

    Replay attacks and nonces in mobile APIs

    A 2026 view of a replay attack where a captured valid request is resent and rejected because its nonce is already spent and its timestamp is outside the validity window

    TLS stops someone from reading or tampering with your app's requests in transit, but it does not stop a captured request from being sent again. If an attacker, or a malicious client, gets hold of a valid request, a payment, a state change, a one-time code, and replays it, the server may happily perform the action a second time. That is a replay attack, and the defense is to make each sensitive request usable exactly once: a nonce the server tracks, a timestamp window, an idempotency key. Here is what replay attacks are and how to protect a mobile API against them.

    Short answer

    A replay attack is when an attacker captures a valid request, token, or message and sends it again to repeat the action it performed, such as re-submitting a payment, reusing a one-time code, or replaying a signed request. Per OWASP, TLS prevents eavesdropping but not replay by a party who has the request, so sensitive operations need explicit replay protection: a nonce (a unique, unpredictable value the server records and rejects if reused), a timestamp with a short validity window, and idempotency keys for operations that must not repeat. These are enforced on the server, since the app is one client and the server is what decides whether to honor a request. Make each sensitive request usable exactly once.

    What you should know

    • A replay re-sends a valid request: to repeat the action it performed.
    • TLS does not prevent it: encryption stops reading, not resending.
    • Sensitive operations are the target: payments, codes, state changes.
    • A nonce makes a request single-use: the server records and rejects reuse.
    • Server-side enforcement: the server decides whether to honor a request.

    What is a replay attack?

    It is reusing a captured valid request to repeat its effect. An attacker who obtains a legitimate request, by capturing it, by being a malicious client, or by getting a token or message, sends it again, and if the server processes it the same way, the action happens twice: a payment is charged again, a one-time code is accepted a second time, a state-changing request is repeated. The point is that the request is genuinely valid, it was authentic the first time, so the server cannot reject it on the grounds of being malformed or unauthenticated; the problem is solely that it is being used more than once. TLS does not help here, since it protects the request from being read or altered in transit but does nothing to stop a party who already has the request from sending it again. So replay protection has to make a sensitive request distinguishable as already-used.

    What are the defenses?

    A few mechanisms that make a request single-use or time-bound. The table lists them.

    DefenseHow it works
    NonceA unique value per request the server records and rejects if reused
    Timestamp windowReject requests older than a short validity period
    Idempotency keyA client-supplied key the server dedupes so an operation runs once
    One-time tokensCodes and reset tokens accepted exactly once
    Sequence numbersMonotonic counters that reject out-of-order reuse

    A nonce, a number used once, is the core mechanism: the client includes a unique, unpredictable value with each sensitive request, and the server records which nonces it has seen and rejects any repeat, so a replayed request fails because its nonce is already spent. A short timestamp window bounds how long any request is valid, so even an unseen replay is rejected if it is stale, and it keeps the nonce-tracking set manageable. Idempotency keys handle operations that must not repeat, like payments: the client sends a unique key, and the server performs the operation once per key, returning the same result for retries instead of repeating it. One-time tokens and sequence numbers apply the same idea to codes and ordered messages.

    How do you add replay protection?

    Make sensitive requests single-use and time-bound, enforced on the server. For requests that perform sensitive or state-changing actions, have the client include a nonce and a timestamp, and on the server reject any request whose timestamp is outside a short window or whose nonce has already been seen, recording nonces for the validity window so reuse is caught. For operations that must not repeat, such as payments or order submission, use idempotency keys so the server performs the action once per key and safely deduplicates retries. Make one-time codes and reset tokens genuinely single-use, invalidating them on first use. Where requests are signed, include the nonce and timestamp in the signed content so they cannot be altered. And keep all of this server-side, since the app is one client and an attacker can resend a request directly; the server is the only place that can refuse a second use. The principle is that a sensitive request should be honored exactly once, and the server enforces that.

    What to watch out for

    The first trap is assuming TLS prevents replay, when it only prevents reading and tampering, not resending; sensitive actions need their own protection. The second is non-idempotent operations like payments without idempotency keys, where a retry or replay charges twice. The third is one-time codes or tokens that are not actually invalidated after use, letting them be replayed. Replay protection is server-side logic, so a pre-submission scan such as PTKD.com (https://ptkd.com), which reads the binary against OWASP MASVS, surfaces the API endpoints and authentication your app uses as the surface to protect, while the nonce, timestamp, and idempotency handling are yours to implement on the backend.

    What to take away

    • A replay attack resends a captured valid request to repeat its action, and TLS does not prevent it, since encryption stops reading, not resending.
    • Defend sensitive operations with a nonce the server records and rejects on reuse, a short timestamp window, and idempotency keys for operations that must not repeat.
    • Make one-time codes and tokens genuinely single-use, include nonces and timestamps in signed content, and enforce all of it on the server.
    • Use a pre-submission scan such as PTKD.com to surface the endpoints and authentication your app uses, then add replay protection server-side.
    • #replay-attack
    • #nonce
    • #idempotency
    • #api-security
    • #authentication
    • #owasp
    • #mobile

    Frequently asked questions

    What is a replay attack?
    It is reusing a captured valid request to repeat its effect. An attacker who obtains a legitimate request, by capturing it, being a malicious client, or getting a token or code, sends it again, and if the server processes it the same way, the action happens twice: a payment charged again, a one-time code accepted a second time, a state change repeated. The request is genuinely valid, so the server cannot reject it as malformed or unauthenticated; the only problem is that it is being used more than once.
    Does TLS prevent replay attacks?
    No. TLS protects a request from being read or altered in transit, but it does nothing to stop a party who already has the request, an attacker who captured it, a malicious client, or someone with a leaked token, from sending it again. So encryption is necessary but not sufficient against replay. Sensitive operations need their own replay protection, such as a nonce the server records and rejects on reuse, a short timestamp window, and idempotency keys for actions that must not repeat.
    What is a nonce?
    A nonce is a number used once: a unique, unpredictable value the client includes with each sensitive request. The server records which nonces it has seen and rejects any request whose nonce has already been used, so a replayed request fails because its nonce is spent. Pairing the nonce with a short timestamp window bounds how long a request is valid, which rejects stale replays and keeps the set of recorded nonces manageable. The nonce is what makes an otherwise valid request usable exactly once.
    How do idempotency keys help?
    They handle operations that must not repeat, like payments or order submission. The client sends a unique idempotency key with the request, and the server performs the operation once per key, returning the same result for any retry with that key instead of repeating the action. This makes retries safe and defeats replay of the same request, since a resend with the same key does not charge or act twice. It is the standard way to make a non-idempotent operation safe against duplication.
    Where is replay protection enforced?
    On the server, since the mobile app is one client and an attacker can resend a request directly, so the server is the only place that can refuse a second use. The client includes a nonce and timestamp, but the server records nonces, enforces the timestamp window, deduplicates idempotency keys, and invalidates one-time tokens after first use. A pre-submission scan such as PTKD.com surfaces the API endpoints and authentication your app uses, but the replay-protection logic is implemented and enforced on the backend.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free