fixes / launch-ready

How I Would Fix exposed API keys and missing auth in a React Native and Expo internal admin app Using Launch Ready.

The symptom is usually obvious: someone finds API keys in the app bundle, a test user can open admin screens without logging in, or internal endpoints are...

How I Would Fix exposed API keys and missing auth in a React Native and Expo internal admin app Using Launch Ready

The symptom is usually obvious: someone finds API keys in the app bundle, a test user can open admin screens without logging in, or internal endpoints are callable from any device. In a React Native and Expo app, the most likely root cause is that security was pushed into the client instead of enforced on the server.

The first thing I would inspect is the actual auth boundary: which screens are protected in the app, which APIs accept requests without a valid token, and whether any secrets were baked into `app.config`, `.env`, or bundled JS. If the app is an internal admin tool, I would assume exposure already happened and treat this as a production incident, not just a code cleanup.

Triage in the First Hour

1. Check whether any secrets are public right now.

  • Review the Expo bundle, EAS build logs, Git history, and any deployed JS artifacts.
  • Confirm whether API keys, service tokens, or private URLs are present in client code or environment files.

2. Verify what is actually unauthenticated.

  • Open the admin app as a logged-out user.
  • Try every privileged screen, route, and action.
  • Confirm whether backend endpoints enforce auth or only hide UI elements.

3. Inspect deployment and access logs.

  • Look at recent traffic spikes, failed login attempts, and unusual requests to admin APIs.
  • Check Cloudflare logs if it is already in front of the app.
  • Review server logs for requests missing authorization headers.

4. Audit build outputs.

  • Inspect Expo/EAS production bundles for hardcoded values.
  • Search for `process.env`, `EXPO_PUBLIC_`, inline config objects, and copied API base URLs.

5. Check secret sources and account access.

  • Rotate exposed keys immediately if they were committed or shipped.
  • Review who has access to Vercel, EAS, GitHub, Cloudflare, backend hosting, and database consoles.

6. Freeze risky changes.

  • Stop new releases until auth is fixed.
  • Pause non-essential deployments so you do not overwrite evidence or ship more exposure.

7. Confirm blast radius.

  • Identify which systems the exposed key can reach: database, email provider, analytics, payment tools, or third-party APIs.
  • Decide whether customer data could be read, modified, or deleted.
## Quick local search for likely secret leaks
grep -RIn --exclude-dir=node_modules --exclude-dir=.git \
  "sk_live\|sk_test\|api_key\|secret\|token\|EXPO_PUBLIC_\|Authorization" .

Root Causes

| Likely cause | What it looks like | How I confirm it | |---|---|---| | Secrets placed in Expo public env vars | Keys appear in built JS or can be read from the app | Search for `EXPO_PUBLIC_` usage and inspect compiled bundles | | Auth enforced only in UI | Admin buttons disappear when logged out, but APIs still work | Call backend endpoints directly without a token and check responses | | Missing server-side authorization | Any authenticated user can access all admin data | Test role-based routes with a low-privilege account | | Hardcoded config in source files | API URLs or keys are pasted into screens or helpers | Search codebase for literal secrets and copied config blocks | | Weak session handling | Tokens never expire or refresh poorly | Review token TTLs, refresh flow, logout behavior, and revocation | | Over-permissive third-party key | A leaked key has broad permissions | Check provider scopes and usage limits in the vendor dashboard |

The biggest mistake I see is founders assuming "internal" means "safe." Internal apps still get attacked through leaked builds, shared devices, compromised accounts, reused passwords, or overbroad vendor credentials.

The Fix Plan

I would fix this in layers so we do not create downtime while closing the hole.

1. Remove secrets from the mobile client.

  • Move private keys to backend-only environment variables.
  • Replace direct third-party calls from the app with calls to your own API proxy where possible.
  • Keep only non-sensitive public values in Expo public config.

2. Rotate every exposed credential.

  • Regenerate API keys that shipped in code or bundles.
  • Revoke old tokens immediately after replacement is deployed.
  • If you cannot tell whether a secret was exposed publicly, assume it was.

3. Enforce auth on the backend first.

  • Require valid access tokens on every privileged endpoint.
  • Add role checks for admin-only actions such as create, edit, delete, export, and invite flows.
  • Never trust route hiding as security.

4. Add session controls that match an admin tool.

  • Use short-lived access tokens with refresh where appropriate.
  • Add logout revocation if your stack supports it.
  • Set idle timeout for internal admin sessions if risk warrants it.

5. Lock down transport and origin paths.

  • Put the deployed app behind HTTPS only with SSL enabled everywhere.
  • Use Cloudflare for caching where safe, DDoS protection, rate limiting if available on your plan level choice set appropriately by risk profile only on login and sensitive endpoints if supported by your architecture path choice then verify no cache leakage of private responses occurs

Wait need concise ASCII punctuation? Need finish article properly no weirdness.

Delivery Map

References

  • [roadmap.sh - API security](https://roadmap.sh/api-security-best-practices)
  • [OWASP API Security Top 10](https://owasp.org/www-project-api-security/)
  • [MDN Web Docs - HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP)
  • [Cloudflare DNS documentation](https://developers.cloudflare.com/dns/)
  • [Sentry documentation](https://docs.sentry.io/)

---

Take the next step

If this is a problem in your product right now, here is what to do next:

  • [Use the free Cyprian tools](/tools) - estimate cost, score app risk, check launch readiness, or pick the right service sprint.
  • [Book a discovery call](/contact) - I will tell you honestly whether you need a sprint or if you can DIY the next step.

*Written by Cyprian Tinashe Aarons - senior full-stack and AI engineer helping founders rescue, launch, automate, and scale AI-built products.*

Next steps
About the author

Cyprian Tinashe AaronsSenior Full Stack & AI Engineer

Cyprian helps founders rescue, secure, deploy, and automate AI-built apps with production-grade engineering, launch systems, and AI integration.