SReverseby Simpa Labs

Token handling

Tracing where a token is built inside an APK

Some tokens come from the server and can be copied out of a capture, while others are computed on the device and no capture contains the rule that produced them. Working out which kind you are holding decides the whole approach.

Two kinds of token

A token in a mobile API is either something the server issued and the app stores, or something the app computes from data it holds. The first kind you can obtain by calling the login endpoint yourself. The second kind has to be rebuilt, because the value is an output and the algorithm is the thing you actually need.

Separate them with an experiment. Send a request with a captured token, then send the same request with one character of the token changed. If both attempts fail the same way, the token is opaque and the server looks it up. If the altered token fails differently, the value carries structure the server parses, and that structure is worth reading.

Follow the token to its origin

Trace the Authorization header, or whichever custom header carries the value, back through the code until you reach the assignment that creates it. The path normally runs through a session manager, an interceptor or a small helper class.

  • Values read from SharedPreferences or EncryptedSharedPreferences were written earlier, usually at login or first launch.
  • Values built inside a method call are derived locally, and this is the case that needs reconstruction.
  • Values fetched from a native library through JNI are derived in C or C++, which changes where you go looking.

Obfuscation renames the methods but rarely changes the shape of this path. A class that holds a token and exposes a getter still looks like that after renaming.

What the derivation is built from

Locally computed tokens come from a small set of inputs pushed through one mixing function.

  • A key, which may be a constant in the code, a string assembled at runtime from several fragments, or a value fetched from a configuration endpoint.
  • Identifying material such as the account identifier, the device identifier, or the package name and signing certificate.
  • Time, which gives the token an expiry and forces a refresh.
  • A counter or random value, which makes each token distinct.

The mixing function is most often HMAC with SHA-256, an AES based construction, or a platform hash. Inside native code it may be a custom arrangement of the same primitives, which is still recoverable once you identify them.

Recover a key that is not stored as a string

Keys assembled at runtime defeat a plain search for a literal. Look for code that concatenates fragments, transforms a resource, or decodes a byte array before use. Dumping the value from memory at the moment the signing function runs is faster than reading the assembly that builds it.

Keys fetched from a server are easier in one way and harder in another. You can capture the fetch and reuse the value, but it may be bound to the account or rotate on a schedule, so your client has to perform the fetch and handle rotation the same way the app does. Treat a fetched key as session state, not as configuration.

Refresh windows and rotation

An expiring token introduces a second mechanism. The app holds an expiry, either from an expires_in field in the response or from its own clock, and asks for a new token before the old one dies. Refresh tokens are frequently single use: the server issues a new refresh token alongside each access token and invalidates the previous one.

Two failures follow. A client that refreshes late sends an expired token and gets rejected. A client that refreshes twice from the same refresh token, which happens when two requests run in parallel and both notice the expiry, invalidates its own credentials. Serialise the refresh and persist the new refresh token before using the access token it came with.

Clock drift causes the same symptom with correct code. A device whose time is minutes off will refresh early or late, so read the expiry from the server response wherever the server provides one.

Confirm the reconstruction

Where the token is deterministic, compare your output with a token the app produced from the same inputs. Where it contains a random component, verify the server accepts yours and rejects a modified copy, then exercise the refresh path including the case where a refresh token has already been spent. That second test is the one that catches most hand built clients.

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?