Skip to main content
Security Best Practices

Module Overview

Estimated Time: 4 hours | Difficulty: Advanced | Prerequisites: Authentication, Storage modules
Security in mobile apps is a different beast from web security. On the web, your code runs on a server you control. In a mobile app, your code runs on the user’s device — a device that might be jailbroken, connected to a malicious WiFi network, or actively being reverse-engineered. Every piece of data you store locally is potentially readable, every network request is potentially interceptable, and your JavaScript bundle can be extracted and decompiled. This is not a reason to panic — it is a reason to think defensively. This module covers comprehensive security practices for React Native apps, from secure storage to preventing reverse engineering. The principle is defense in depth: no single measure is bulletproof, but layers of protection raise the cost of attack until it is not worth the effort. What You’ll Learn:
  • Secure storage solutions
  • Certificate pinning
  • Code obfuscation
  • Jailbreak/root detection
  • Data encryption
  • Security auditing

Security Threat Model


Secure Storage

The most common security mistake in React Native apps is storing sensitive data (auth tokens, API keys, user credentials) in AsyncStorage or plain files. AsyncStorage is backed by an unencrypted SQLite database on Android and an unencrypted plist on iOS — anyone with physical device access (or a jailbroken device) can read it trivially. Secure storage uses the platform’s hardware-backed security: iOS Keychain and Android Keystore. Data stored here is encrypted at the OS level, protected by the device lock, and inaccessible to other apps.

expo-secure-store

For sensitive data like tokens and credentials:

react-native-keychain (CLI)

For React Native CLI projects:

Encrypted Storage with MMKV


Certificate Pinning

Standard HTTPS validates that a server’s certificate was issued by a trusted Certificate Authority (CA). But what if an attacker compromises a CA, or installs a rogue root certificate on the user’s device (common in corporate environments or jailbroken devices)? They could issue a valid-looking certificate for your API domain and intercept all traffic. Certificate pinning solves this by telling your app to trust only specific certificates or public keys for your domain, not the entire CA chain. Think of it as adding a secret handshake on top of the standard TLS process.
Certificate rotation pitfall: When your server certificate expires and you rotate it, pinned apps will immediately break because the new certificate does not match the pin. Always include a backup pin for your next certificate, and plan rotation carefully. Some teams pin the public key of an intermediate CA certificate rather than the leaf, giving more rotation flexibility.

Using react-native-ssl-pinning

Using Axios with Certificate Pinning


Code Obfuscation

Your React Native app’s JavaScript bundle can be extracted from the APK/IPA file in minutes. Without obfuscation, an attacker can read your business logic, API endpoints, validation rules, and any hardcoded strings in plain text. Obfuscation does not make reverse engineering impossible — it makes it expensive and time-consuming enough to deter casual attackers.

JavaScript Obfuscation

Android ProGuard


Jailbreak/Root Detection

Jailbroken (iOS) and rooted (Android) devices have their security sandbox removed. On these devices, other apps can read your app’s data, inject code, or attach debuggers. Detection is not foolproof — sophisticated users can bypass it — but it raises the bar and lets you make informed decisions about what functionality to allow. The practical question is: should you block jailbroken devices entirely, or just restrict sensitive features? Most apps take the second approach: banking and payment features require a secure device, but browsing and reading do not.

Security Provider Component


Data Encryption

Sometimes you need to store structured data (not just simple strings) securely. Secure Store and Keychain have size limits and are designed for small values like tokens. For larger data — like cached user profiles, draft messages, or offline records that contain PII — you need application-level encryption on top of regular storage. The pattern: generate an encryption key on first launch, store it in Secure Store (hardware-protected), and use it to encrypt/decrypt data before writing to AsyncStorage or MMKV.

Encrypting Sensitive Data


Biometric Authentication

Biometric auth (Face ID, Touch ID, fingerprint) does not replace password authentication — it provides a faster way to re-authenticate returning users. The typical flow: user logs in with email/password on first use, tokens are stored in Secure Store protected by biometric access control, and subsequent launches prompt for biometric verification to unlock the stored tokens.

Biometric Login Component


Preventing Screenshot/Screen Recording

For financial, healthcare, or enterprise apps, preventing screenshots and screen recordings protects sensitive data from being casually shared. Android supports programmatic prevention via the FLAG_SECURE window flag. iOS does not support prevention (Apple intentionally prevents this), but you can detect screenshots and respond (show a warning, log a security event, or blur sensitive content).

Choosing the Right Storage for Sensitive Data

The most common security mistake is using the wrong storage mechanism for the sensitivity level of the data. Here is a decision matrix:
expo-secure-store has a 2KB value limit on iOS (backed by iOS Keychain). If you need to store larger encrypted payloads (e.g., a cached user profile with 50+ fields), use MMKV with an encryption key that lives in Secure Store. Do not try to split large values across multiple Secure Store keys — the API is not designed for that pattern and you will hit race conditions.

Certificate Pinning Decision Framework

Certificate pinning adds meaningful security but introduces operational complexity. Not every app needs it. Leaf vs. intermediate vs. root pinning: My recommendation: Pin the intermediate CA’s public key. This gives you strong MITM protection while allowing leaf certificate rotation without app updates. Always include a backup pin for the next intermediate you plan to use.

Edge Cases in Mobile Security

Token Refresh Race Condition

When multiple API calls fail simultaneously with a 401 (expired token), each one independently triggers a token refresh. This can cause multiple refresh requests, and if the server invalidates the refresh token on first use (which it should for security), all but the first refresh call fail — cascading into a forced logout.

Clipboard Data Leakage

When users copy sensitive data (account numbers, one-time codes), it sits on the system clipboard accessible to any app. On Android, clipboard managers can even persist clipboard history across app switches.
Deep links (myapp://reset-password?token=xyz) can be crafted by malicious apps or websites to inject parameters into your navigation. If your app blindly trusts deep link parameters, an attacker can bypass auth flows or trigger unintended actions.

Background App Snapshot Exposure

Both iOS and Android capture a screenshot of your app when it moves to the background (for the app switcher). If your app displays sensitive data (bank balances, health records, personal messages), this screenshot is visible to anyone who opens the task switcher.

Security Checklist

Storage Security

  • Use SecureStore for tokens
  • Encrypt sensitive data
  • Clear data on logout
  • No hardcoded secrets

Network Security

  • Use HTTPS only
  • Implement certificate pinning
  • Validate SSL certificates
  • Add request signing

Code Security

  • Enable ProGuard/R8
  • Remove debug logs
  • Obfuscate JavaScript
  • No sensitive data in logs

Runtime Security

  • Detect jailbreak/root
  • Prevent debugging
  • Screen capture protection
  • Clipboard security

Security Audit Script


Next Steps

Module 32: Offline-First Architecture

Learn to build apps that work seamlessly without internet connectivity