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.
Related work
Reviewed 28 September 2026 · SReverse research desk