Thuta Learning
AdvancedMobile Developmentintermediate

Mobile Secret Management

What you'll walk away with

  • Explain the core ideas behind Mobile Secret Management
  • Read the diagram/checklist and trace how the mobile architecture or decision connects
  • Explain how this applies to a real mobile app project

Build the mental model

A mobile app binary is not a private thing. It gets downloaded, installed, and stored on devices you do not control, potentially for years, across multiple versions, in the hands of anyone who cares to look closely.

Treat every build as inspectable

Someone with the right tools can decompile an app binary, extract embedded strings, and read anything bundled directly inside it -- regardless of the framework that produced it.

An API key, a server credential, a signing secret for some third-party service -- none of it is actually secret once it ships inside an app binary, no matter how it is obfuscated or encoded. Obfuscation slows someone down; it does not stop them.

If a credential grants real privilege -- write access to a database, the ability to charge a payment method, admin rights on a third-party service -- it must never live inside the app itself.

The fix is architectural, not clever hiding: your backend holds the real secret credential, and the app talks only to your backend, which then talks to the third-party service on the server's behalf.

This matters more on mobile than the web, because a web deployment can be patched and redeployed in minutes, while an app binary already on millions of devices cannot be un-shipped -- only replaced by a future update those devices may not install for a long time, if ever.

text
BACKEND-PROXY PATTERN FOR MOBILE SECRETS
----------------------------------------
BACKEND-PROXY PATTERN FOR MOBILE SECRETS
-------------------------------------------
GOOD PATTERN
  Mobile App --> Your Backend (holds secret) --> 3rd-party API

BAD PATTERN (do not do this)
  Mobile App --> [Secret Bundled Directly] --> 3rd-party API
                     X inspectable in the shipped binary

Connect it to a real scenario

Do a pass over every configuration value baked into your app right now and sort each one into two piles.

  • Fine to keep in the app: a base API URL, a publishable/restricted client key, an analytics id.
  • Must never be in the app: anything that can write data, move money, or act with admin rights.

Watch for two sneaky versions of this mistake: a key that looks harmless today but becomes privileged later after a permission change in a dashboard, and a secret that sits in a config file or environment file that still ends up packaged into the shipped binary.

Watch third-party SDKs too

Some SDKs ask you to embed a secret key directly in the app -- that's a sign the SDK wasn't designed for mobile's inspectable-binary reality. Look for a server-side integration option instead.

A mobile app binary should be considered inspectable

Never bundle a privileged secret in a mobile app binary -- treat it as inspectable by anyone with technical means, no matter how it is obfuscated. Server-only credentials belong on your backend, never in the app.

Try the working example

javascript
function scanConfigForBundledSecrets(config) {
  const secretPattern = /secret|private[_-]?key|server[_-]?key/i;
  const safeMarkers = ["via-backend", "proxied"];
  const flagged = [];

  for (const [key, value] of Object.entries(config)) {
    if (safeMarkers.includes(value)) continue;
    const looksPrivileged = secretPattern.test(key);
    if (looksPrivileged) {
      flagged.push({ key, reason: "Looks like a privileged secret bundled directly in the app." });
    }
  }

  return { flaggedCount: flagged.length, flagged };
}

const riskyConfig = {
  STRIPE_SECRET_KEY: "sk_live_51H8xExampleNotReal",
  PAYMENT_SERVER_SECRET: "ex_srv_secret_998877",
  MAPS_API_KEY: "AIzaRestrictedPublicKeyExample"
};

const saferConfig = {
  STRIPE_SECRET_KEY: "via-backend",
  PAYMENT_SERVER_SECRET: "via-backend",
  MAPS_API_KEY: "AIzaRestrictedPublicKeyExample"
};

console.log("Risky config:", scanConfigForBundledSecrets(riskyConfig));
console.log("Safer config:", scanConfigForBundledSecrets(saferConfig));
You should see
The risky config flags 2 keys (STRIPE_SECRET_KEY, PAYMENT_SERVER_SECRET) as privileged secrets bundled directly, returning flaggedCount: 2. The safer config marks both as 'via-backend' and returns flaggedCount: 0.

5-minute try-it

List every configuration value currently bundled in one of your projects (or a hypothetical one). Run each through the scanConfigForBundledSecrets-style function and move any flagged value behind a backend endpoint instead.

One important caution

Assuming obfuscation or code minification makes a bundled secret actually secret -- it does not.

Accepting a third-party SDK's instructions to embed a secret key directly in the mobile app without checking for a server-side alternative.

OWASP Mobile Application Security (MASTG)How Mobile Apps Work

Easy traps

  • Assuming obfuscation or code minification makes a bundled secret actually secret -- it does not.
  • Accepting a third-party SDK's instructions to embed a secret key directly in the mobile app without checking for a server-side alternative.
  • This course does not re-teach the Android Development, Flutter, iOS Development, or React Native tutorials -- continue to those for hands-on framework depth. This course teaches the framework-neutral mobile architecture, decision-making, and build/deployment/security concepts that sit above all four.

Exercise

List every configuration value currently bundled in one of your projects (or a hypothetical one). Run each through the scanConfigForBundledSecrets-style function and move any flagged value behind a backend endpoint instead.

You'll know it worked when: The risky config flags 2 keys (STRIPE_SECRET_KEY, PAYMENT_SERVER_SECRET) as privileged secrets bundled directly, returning flaggedCount: 2. The safer config marks both as 'via-backend' and returns flaggedCount: 0.

Mobile Secret Management | Thuta Learning