SReverseby Simpa Labs

Protected builds

When the backend verifies device integrity

Some APIs answer only clients that can prove where they run. The proof is produced on the device, bound to the request, and verified by the server before any application logic runs.

What the server adds to the client API specification

An integrity verdict is a credential generated by the device and sent with a request, and the server decides whether to answer based on it. Google Play Integrity is the common source on Android, and a distributor-specific service plays the same role elsewhere. The verdict describes the app, the device and the account context, and it is signed by the service that produced it so the server can trust it without trusting the client.

The practical consequence is that a client which cannot obtain a verdict cannot reach the endpoint's data, because the refusal happens before the parameters are read. Automation, batch work and a server-side integration therefore depend on whatever the server actually enforces rather than on the HTTP shape of the call.

Why the signal is bound to a nonce or request hash

A verdict on its own is a portable string. Anyone who observes one could attach it to their own traffic, so servers that care about binding include something specific to the request inside the integrity check. The two common patterns are a service-issued nonce and a hash computed over the request.

A nonce flow starts with the client asking the backend for a challenge. The app passes that value into the integrity call, the service signs it into the verdict, and the server verifies that the returned token carries the challenge it issued and has not been used before. A hash flow binds the verdict to the request itself: the client hashes the body and part of the request, includes the hash as the challenge input, and the server recomputes the same hash. Both make the verdict valid for one request or one short window.

That binding explains failures that look arbitrary. A replay of a captured verdict fails because the challenge is spent. A request edited after capture fails because the hash no longer matches. Short-lived challenges fail when the clock or the ordering of the flow changes. It also explains why the check lives near the start of request handling: the server cannot accept the payload before it has decided to trust the sender.

What a missing or stale signal produces

The failure mode is usually an explicit refusal rather than a crash, and the shape of the refusal points at the integrity layer. The server rejects the call before interpreting the parameters, so an obviously malformed body and a perfectly valid one receive the same response. It may also answer with an empty payload or a generic message that hides which check failed.

Staleness is harder to distinguish than absence because the request is well formed. A verdict issued for an earlier request can be complete, correctly signed and still refused. Where the response does not name the reason, the useful evidence is timing and repetition: a request that succeeds once and fails on an immediate resend is enforcing uniqueness, and a request that fails only after a pause is enforcing freshness.

Some applications treat integrity as advice rather than as a gate. The verdict arrives, the server records it, and the request proceeds even when the verdict is poor. Those backends fail for reasons unrelated to integrity, and an analysis that assumes enforcement will spend days in the wrong layer.

Establishing whether the server enforces it

Enforcement is a question of server behaviour, and it can be answered with a captured request that is known to succeed. The tests are ordered from the least invasive to the most.

  • Remove the integrity field and resend. If the protected response changes, the server noticed its absence and the endpoint gates on it. If the response is unchanged, the field may be logged and ignored, or it may be optional for this endpoint and required for a different one.
  • Send the same verdict twice. A second refusal on an otherwise valid request demonstrates that the binding is real and not an incidental signature that happens to cover the field.
  • Change one character of the request body and keep the verdict. A hash-bound flow refuses, while a server that checks the verdict for validity alone accepts, which tells you which of the two bindings you face.
  • Check whether the request asks for a nonce first. A preliminary call that returns a challenge is strong evidence of a bound verdict, and its absence suggests either a different binding scheme or no binding.

Once enforcement is established, the deliverable is a client that performs the same exchange: obtain whatever the server issues, include it correctly, and preserve the request bytes that the hash covers. That work ends in a callable API with documentation and test runs, and those projects start at $120 with most delivered in 24 to 72 hours.

Reviewed 28 September 2026 · SReverse research desk

Start your full APK reconstruction

Send the full APK

Projects start at $120. Choose WhatsApp or email, then attach the APK in the app that opens. We reply within one hour with the next step and send the fixed quote after review.

Want us to contact you?