Module Overview
Estimated Time: 4 hours | Difficulty: Advanced | Prerequisites: Authentication, Storage modules
- 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.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 theFLAG_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: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 Link Injection
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