Mobile App Security: A Developer's Checklist for 2026
A comprehensive mobile app security checklist covering authentication, data encryption, network security, code protection, and OWASP Mobile Top 10 — with actionable implementation guidance.
Mobile apps handle sensitive data — financial transactions, health records, personal communications, location history, biometric identifiers. A single security breach can destroy user trust, trigger regulatory penalties, and end a product. Yet mobile security is consistently under-invested compared to web security, in part because developers assume the app stores provide adequate protection.
They do not. App store review catches malware and policy violations, not architectural security flaws. Your app's security is your responsibility.
This checklist covers the security controls that every production mobile app should implement, organized around the OWASP Mobile Top 10 (2024 edition) and supplemented with practical implementation guidance for iOS and Android.
OWASP Mobile Top 10: The Threat Landscape
The Open Web Application Security Project (OWASP) maintains the Mobile Top 10 — the most critical security risks for mobile applications. Understanding these threats frames every security decision you make.
| # | Risk | Impact |
|---|---|---|
| M1 | Improper Credential Usage | Account takeover, data theft |
| M2 | Inadequate Supply Chain Security | Malicious code injection via dependencies |
| M3 | Insecure Authentication/Authorization | Unauthorized access to user accounts |
| M4 | Insufficient Input/Output Validation | Injection attacks, data corruption |
| M5 | Insecure Communication | Man-in-the-middle attacks, data interception |
| M6 | Inadequate Privacy Controls | Regulatory violations, user data exposure |
| M7 | Insufficient Binary Protections | Reverse engineering, code tampering |
| M8 | Security Misconfiguration | Exposed debug features, weak defaults |
| M9 | Insecure Data Storage | Local data theft from compromised devices |
| M10 | Insufficient Cryptography | Broken encryption, exposed keys |
Every item in this checklist maps to one or more of these risks.
Authentication and Authorization
Authentication is the most attacked surface of any mobile app. Get it wrong and everything else is irrelevant.
Implement Modern Authentication Standards
-
Use OAuth 2.0 with PKCE (Proof Key for Code Exchange) for all third-party authentication flows. PKCE prevents authorization code interception attacks that are specific to mobile apps where you cannot securely store client secrets.
-
Never store passwords locally. Use token-based authentication where the server issues short-lived access tokens and longer-lived refresh tokens. Store tokens in platform-secure storage (Keychain on iOS, EncryptedSharedPreferences on Android).
-
Enforce strong password policies server-side: minimum 10 characters, check against breached password databases (HaveIBeenPwned API), support passkeys and WebAuthn for passwordless authentication.
Biometric Authentication
- Use platform biometric APIs (
LocalAuthenticationon iOS,BiometricPrompton Android) — never build custom biometric handling - Biometrics should unlock locally-stored credentials, not replace server authentication
- Provide fallback authentication (PIN, password) for users without biometric hardware
- Handle biometric enrollment changes — if a user adds a new fingerprint, consider re-authentication
Session Management
- Access tokens: 15-30 minute expiry maximum
- Refresh tokens: 7-30 day expiry, single-use (rotate on each refresh)
- Implement token revocation: when a user logs out or changes their password, invalidate all active tokens server-side
- Detect concurrent sessions: alert users when their account is accessed from a new device
- Bind sessions to devices: include a device fingerprint in the token payload to prevent token theft across devices
Authorization Controls
- Enforce authorization on every API endpoint server-side — never rely on client-side checks
- Use role-based access control (RBAC) or attribute-based access control (ABAC) with least-privilege defaults
- Validate that the authenticated user has permission to access the requested resource (prevent IDOR — Insecure Direct Object Reference)
- Implement rate limiting on authentication endpoints: 5 failed attempts triggers a 15-minute lockout
Data Encryption
Encryption protects data at two stages: at rest (stored on the device) and in transit (moving across the network).
Encryption at Rest
-
iOS: Use the Data Protection API with
NSFileProtectionComplete— files are encrypted with a key derived from the user's passcode and the device UID. Files are inaccessible when the device is locked. -
Android: Use
EncryptedFileandEncryptedSharedPreferencesfrom the Jetpack Security library. These use AES-256-GCM encryption with keys stored in the Android Keystore. -
SQLite databases: Use SQLCipher for encrypted local databases. Enable full database encryption, not just column-level encryption.
-
Never store sensitive data in:
UserDefaults/SharedPreferences(unencrypted by default)- Application cache directories
- External storage (Android)
- Clipboard (which is accessible to other apps)
- Application logs
Encryption in Transit
- Enforce TLS 1.3 (or TLS 1.2 minimum) for all network communication
- Implement certificate pinning — pin against the leaf certificate or the public key, not the root CA
- Use Network Security Configuration (Android) and App Transport Security (iOS) to enforce HTTPS
- Disable fallback to plaintext HTTP — even for development, use self-signed certs over TLS
Cryptographic Best Practices
- Use platform-provided cryptographic APIs — never implement your own crypto
- AES-256-GCM for symmetric encryption
- RSA-2048 or ECDSA P-256 for asymmetric encryption
- SHA-256 minimum for hashing (SHA-3 preferred for new implementations)
- Use
SecRandomCopyBytes(iOS) orSecureRandom(Android) for random number generation - Rotate encryption keys periodically and maintain key versioning
Network Security
The network layer is where attackers most commonly intercept data.
Certificate Pinning Implementation
Certificate pinning prevents man-in-the-middle attacks even if an attacker has a trusted CA certificate installed on the device.
iOS — Use URLSession with a custom URLSessionDelegate that validates the server's certificate against pinned public keys:
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust,
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let serverKey = publicKey(from: certificate)
if pinnedKeys.contains(serverKey) {
completionHandler(.useCredential, URLCredential(trust: serverTrust))
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
Android — Use OkHttp's CertificatePinner:
val client = OkHttpClient.Builder()
.certificatePinner(
CertificatePinner.Builder()
.add("api.yourapp.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build()
)
.build()
Critical: Include backup pins. If your primary certificate expires and you only have one pin, your app will stop working until you ship an update.
API Security
- Authenticate every API request with bearer tokens in the Authorization header
- Use request signing (HMAC) for sensitive operations (payments, account changes)
- Implement replay protection with nonces or timestamps
- Validate all response data — do not trust API responses blindly
- Use API versioning to safely evolve your backend without breaking security assumptions
Network Configuration Hardening
- Disable cleartext traffic entirely (
android:usesCleartextTraffic="false"on Android, App Transport Security on iOS) - Configure proper timeout values to prevent slow-loris style attacks
- Implement exponential backoff for retries to avoid amplifying DDoS attacks
- Log network errors securely — never log request/response bodies that may contain sensitive data
Secure Data Storage
Every piece of data your app stores is a potential liability if the device is compromised.
Platform Secure Storage
| Data Type | iOS | Android |
|---|---|---|
| Tokens / credentials | Keychain (kSecAttrAccessibleWhenUnlocked) | EncryptedSharedPreferences |
| Sensitive files | Data Protection API | EncryptedFile |
| Database | Core Data + NSFileProtection | SQLCipher / Room + EncryptedFile |
| Temporary sensitive data | Memory only, zero on dealloc | Memory only, zero on GC |
Data Minimization
- Only collect data your app actually needs — GDPR's data minimization principle is good security practice regardless of jurisdiction
- Set data retention periods and automatically purge expired data
- When a user deletes their account, remove all local data including cached files, database records, and Keychain/Keystore entries
- Do not log sensitive information (PII, tokens, passwords) even in debug builds
Clipboard Protection
- Clear the clipboard after a short timeout when your app copies sensitive data (OTP codes, passwords)
- On iOS 14+, users see clipboard access notifications — avoid unnecessary clipboard reads
- Consider using
UIPasteboard.general.setItems([], options: [.expirationDate: Date().addingTimeInterval(60)])for auto-expiring clipboard content
Code Protection and Binary Security
A determined attacker with physical access to a device can extract, decompile, and analyze your app binary.
Obfuscation
- Android: ProGuard/R8 is enabled by default in release builds. Ensure your
proguard-rules.prodoes not keep more classes than necessary. Consider DexGuard for advanced obfuscation. - iOS: Swift and Objective-C are compiled to machine code, which provides some inherent protection. Use tools like SwiftShield for symbol obfuscation.
- Flutter: Use
--obfuscate --split-debug-infoflags for release builds - React Native: Hermes AOT compilation provides better protection than raw JavaScript. Consider tools like react-native-obfuscating-transformer.
Tamper Detection
- Verify the app's code signature at runtime to detect repackaging
- Check for debugger attachment (
sysctlon iOS,/proc/self/statuson Android) - Detect root/jailbreak and adjust behavior (warn users, disable sensitive features, or refuse to run — depending on your risk tolerance)
- Implement integrity checks on critical binary sections
Reverse Engineering Mitigation
- Strip debug symbols from release builds
- Avoid hardcoding API keys, secrets, or encryption keys in the binary
- Use dynamic configuration delivery for sensitive values
- Implement server-side logic for critical business rules — anything in the client can be reverse-engineered
Dependency and Supply Chain Security
Third-party libraries are the most overlooked attack vector in mobile development. The OWASP Mobile Top 10 elevated supply chain security to the #2 risk in 2024.
Dependency Management
- Audit every dependency before adding it. Check the maintainer's reputation, the library's update frequency, and known vulnerabilities.
- Pin dependency versions — never use floating version ranges in production (
^1.0.0is acceptable in development,1.0.7is required in production) - Run vulnerability scanning regularly:
- Android:
./gradlew dependencyCheckAnalyze(OWASP Dependency Check) - iOS:
auditin Swift Package Manager, or Snyk/Dependabot for CocoaPods - Flutter:
dart pub outdatedcombined with Snyk or Trivy
- Android:
- Review transitive dependencies — your direct dependency may be secure, but its dependencies may not be
- Remove unused dependencies — every dependency is attack surface
Build Pipeline Security
- Use reproducible builds where possible
- Sign all release builds with hardware-protected keys (not checked into source control)
- Verify the integrity of build tools and CI/CD infrastructure
- Implement code review requirements for dependency updates
Privacy Controls
Privacy is both a security concern and a legal requirement under GDPR, CCPA, PIPEDA, and other regulations.
Data Collection Transparency
- Implement a clear privacy dashboard where users can see what data your app collects
- Provide granular consent controls — do not bundle location tracking with analytics consent
- Honor platform privacy frameworks (App Tracking Transparency on iOS, Google's Privacy Sandbox on Android)
- Submit accurate privacy nutrition labels / data safety sections to the app stores
Location Data
- Request location access only when actively needed — use "While Using" permission, not "Always"
- Reduce location precision when full accuracy is not required (iOS offers approximate location)
- Do not store location history locally unless it is a core feature
- Anonymize location data before sending to analytics services
Logging and Diagnostics
- Never log PII, tokens, passwords, or financial data
- Use structured logging with severity levels — ensure production builds suppress debug/verbose logs
- If you use crash reporting services (Firebase Crashlytics, Sentry), configure them to strip PII from crash reports
- Implement log rotation and automatic deletion of local log files
Security Testing
Security controls are worthless if they are not tested.
Static Analysis (SAST)
- MobSF (Mobile Security Framework): Open-source automated analysis for Android and iOS binaries
- Semgrep: Static analysis with mobile-specific rulesets
- Android Lint with security rules enabled
- SwiftLint with security-focused custom rules
Dynamic Analysis (DAST)
- Frida: Runtime instrumentation for testing certificate pinning, tamper detection, and data storage
- Burp Suite / OWASP ZAP: Proxy-based testing of API communication
- Objection: Runtime mobile exploration toolkit built on Frida
- Drozer: Android-specific dynamic analysis
Penetration Testing Checklist
Run these checks before every major release:
- Attempt to bypass certificate pinning with a proxy
- Extract and decompile the app binary — check for hardcoded secrets
- Inspect local storage for unencrypted sensitive data
- Test authentication bypass by manipulating tokens
- Verify authorization — attempt to access another user's data
- Test input validation with injection payloads (SQL, XSS, command injection)
- Check for insecure deep link handling
- Verify session invalidation on logout and password change
- Test behavior on rooted/jailbroken devices
- Inspect network traffic for data leakage
Platform-Specific Security Features
iOS
- App Attest: Verify that API requests come from a legitimate, unmodified instance of your app
- Keychain Access Groups: Share credentials securely between your apps
- Managed App Configuration: For enterprise-deployed apps, receive security policies from MDM
- App Transport Security: Enforce HTTPS with TLS 1.2+ (enabled by default)
Android
- SafetyNet / Play Integrity API: Verify device integrity and app authenticity
- Android Keystore: Hardware-backed key storage on supported devices
- Scoped Storage: Limits app access to only its own files (Android 10+)
- Credential Manager: Unified API for passwords, passkeys, and federated sign-in
Incident Response Planning
Security is not just prevention — it is also preparation for when things go wrong.
- Define a security incident response procedure before you need one
- Implement remote session revocation — the ability to force-logout all users if tokens are compromised
- Build a remote kill switch for sensitive features (payments, data export)
- Maintain an audit log of security-relevant events (login attempts, permission changes, data exports)
- Have a communication plan for notifying affected users within the timeframe required by applicable regulations (72 hours under GDPR)
Implementation Priority
Not every control needs to be implemented on day one. Prioritize based on risk:
Must Have (Before Launch)
- TLS for all communication
- Secure token storage (Keychain / EncryptedSharedPreferences)
- OAuth 2.0 with PKCE
- Server-side authorization on every endpoint
- Input validation
- ProGuard/R8 (Android) or release mode compilation (iOS)
- No hardcoded secrets
Should Have (Within 30 Days)
- Certificate pinning
- Biometric authentication
- SQLCipher for sensitive local data
- Root/jailbreak detection
- Dependency vulnerability scanning
- Crash reporting with PII stripping
Nice to Have (Ongoing)
- App Attest / Play Integrity
- Advanced obfuscation (DexGuard / SwiftShield)
- Runtime tamper detection
- Automated penetration testing in CI/CD
- Bug bounty program
For teams building new mobile applications, our mobile app development services integrate security best practices from day one — not as an afterthought. If you are concerned about the security posture of an existing app, reach out for a security assessment.
FAQ
How often should we perform security audits on our mobile app?
Conduct a full security audit before initial launch, then at least annually for apps handling sensitive data (financial, health, PII). Additionally, perform targeted security reviews before any major release that changes authentication, data handling, or introduces new third-party integrations. Automated scanning (SAST/DAST) should run on every build in your CI/CD pipeline.
Is certificate pinning still necessary with TLS 1.3?
Yes. TLS 1.3 secures the transport channel, but certificate pinning ensures your app only communicates with your specific server — not an attacker's server with a valid certificate from a compromised or coerced certificate authority. These are complementary protections. TLS encrypts the connection; pinning authenticates the endpoint beyond CA trust.
Should we block users on rooted/jailbroken devices?
It depends on your risk tolerance and user base. Banking and healthcare apps commonly block rooted/jailbroken devices because the security controls of the operating system cannot be trusted. Consumer apps typically warn users but allow continued use. A balanced approach is to detect the device state, log it for analytics, and restrict only the most sensitive features (biometric auth, saved payment methods) while allowing general app usage.
How do we handle security in cross-platform frameworks like Flutter or React Native?
Cross-platform frameworks add a layer of abstraction, but the security principles remain identical. Use platform-specific secure storage via plugins (flutter_secure_storage, react-native-keychain), implement certificate pinning at the HTTP client level, enable code obfuscation in release builds, and ensure all security-critical logic runs server-side. The framework does not excuse you from platform security best practices — it just changes how you access them.
Need Help With Your Project?
Our team of experts is ready to help you build, grow, and succeed. Get a free consultation today.
Book Free Consultation