An API Key in Your App Is a Key You've Already Published
1 min read
Two rules, every app, no exceptions.
No secrets in the shipped binary. Anything on a user’s phone can be pulled apart. An API key in a Flutter asset or a Kotlin constant is a key you have published. Keys live on the server, the app gets short-lived tokens, and the token exchange is the only thing the app knows how to do before login.
Every request to my backend is signed. The app signs each request with HMAC over the method, path, timestamp and body. The server recomputes it and drops anything that does not match or is older than a few minutes. It does not stop a determined attacker with a rooted phone. It stops the ninety percent of abuse that is someone replaying a request they saw in a proxy.
Neither takes more than a day to set up on a new project, and both are boring. That is the point. A replayed request is valid in every way except the signature, and the signature is the only thing the server checks that the attacker cannot copy forward.
If you ship mobile apps and do only one of these, do the first one.