
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Shipping a mobile application without a hardened security foundation exposes user data and business logic to interception, tampering, and credential theft. Understanding mobile app security basics is no longer optional for developers or founders; it is the baseline requirement for trust and compliance in 2026. This guide cuts through theoretical frameworks to provide concrete, implementable controls for secure storage, network communication, and authentication that work across both iOS and Android platforms.
How do you securely store sensitive data in mobile apps?
The most frequent failure I see in audits is storing tokens, PII, or credentials in SharedPreferences (Android) or UserDefaults (iOS). These are plaintext XML or plist files readable by any process with app access or via backup extraction. Secure storage requires hardware-backed keystores that isolate cryptographic material from the application runtime.
Use platform-native encrypted storage
Android provides the EncryptedSharedPreferences API backed by the Android Keystore System. iOS offers Keychain Services with accessibility attributes that restrict access to unlocked devices. Never roll your own encryption wrapper around standard preferences; the key management complexity introduces subtle bugs.
// Android: Secure token storage with EncryptedSharedPreferences
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val securePrefs = EncryptedSharedPreferences.create(
context,
"secure_token_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
// Store auth token securely
securePrefs.edit()
.putString("auth_token", accessToken)
.apply() For iOS, always set kSecAttrAccessibleWhenUnlockedThisDeviceOnly to prevent tokens from appearing in iCloud backups or being accessible when the device is locked. This single attribute prevents an entire class of forensic extraction attacks.
Data classification drives storage decisions
Not all data needs keystore-level protection. Classify data into three tiers before writing storage code:
- Secrets: Auth tokens, API keys, private keys → Hardware keystore only
- Sensitive: User PII, health data, financial records → Encrypted database (SQLCipher) or encrypted file storage
- Public: UI preferences, cached content, non-sensitive metadata → Standard storage acceptable
This classification aligns with compliance frameworks like SOC 2 and ISO 27001. During audits, reviewers will ask for evidence of data classification policies mapped to technical controls. Having this documented before development starts saves weeks of remediation later. For teams managing backend databases alongside mobile clients, understanding PostgreSQL administration essentials ensures server-side storage matches mobile-side security posture.
How do you secure mobile API communication against interception?
TLS alone is insufficient for mobile apps. Certificate authorities can be compromised, corporate proxies can intercept traffic, and users can install malicious root certificates. Defense-in-depth network security requires TLS 1.3 enforcement combined with certificate pinning and payload-level protections.
Implement certificate pinning correctly
Certificate pinning binds your app to specific server certificates or public keys, rejecting connections even if a valid CA-signed certificate is presented. Pin the Subject Public Key Info (SPKI) hash rather than the full certificate to allow certificate rotation without app updates.
# OkHttp certificate pinner configuration (Kotlin)
val certificatePinner = CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=") // backup pin
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.sslSocketFactory(Tls13OnlySocketFactory(), trustManager)
.build() Always include at least one backup pin. I have seen production outages where a primary certificate expired and the app had no fallback, requiring an emergency app store update. Test pinning failures explicitly in CI using tools like TrustKit or custom test harnesses.
Enforce network security configuration
Android's Network Security Config and iOS's App Transport Security (ATS) provide declarative network policies. Disable cleartext traffic globally and whitelist only trusted domains. This prevents accidental HTTP requests from leaking data before they reach production.
What authentication patterns prevent session hijacking in mobile?
Mobile authentication differs fundamentally from web authentication. Cookies are unreliable, browsers handle redirects differently, and biometric sensors provide capabilities unavailable on desktop. Secure mobile auth binds sessions to device-specific factors and minimizes token exposure surface area.
Bind tokens to device attestation
Use Android SafetyNet/App Attest (iOS) to generate device-bound tokens. When your backend issues refresh tokens, tie them to the attestation result. If a token extracted from a rooted device appears on a different device fingerprint, revoke it immediately. This limits the blast radius of credential theft.
Implement biometric authentication correctly
Biometrics should unlock stored credentials, not replace them. The pattern is: authenticate with biometrics → retrieve token from keystore → use token for API calls. Never store passwords or tokens in biometric-protected storage directly; store only the decryption key. This ensures biometric compromise does not equal credential compromise.
// iOS: Biometric-gated keychain access
let context = LAContext()
context.localizedCancelTitle = "Enter Passcode Instead"
var error: NSError?
guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
// Fallback to passcode or PIN entry
return
}
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
localizedReason: "Access secure account data") { success, evalError in
if success {
// Retrieve token from Keychain with kSecAttrAccessibleWhenUnlockedThisDeviceOnly
let token = KeychainHelper.retrieveToken()
// Use token for authenticated API call
}
} Short-lived access tokens with secure refresh
Access tokens should expire in 15 minutes or less. Refresh tokens live longer but require device binding and rotation on each use. Implement refresh token rotation: every time a refresh token is used, issue a new refresh token and invalidate the old one. If a stolen refresh token is reused after rotation, detect the replay and revoke the entire token family. Teams integrating with Laravel backends should review building REST APIs with Laravel Sanctum for proper token lifecycle management.
How do platform-specific security controls differ between iOS and Android?
While security principles transfer across platforms, implementation details diverge significantly. Understanding these differences prevents copy-paste vulnerabilities where Android patterns fail silently on iOS or vice versa.
| Control Area | Android Implementation | iOS Implementation | Common Pitfall |
|---|---|---|---|
| Secure Storage | EncryptedSharedPreferences + Keystore | Keychain Services + Data Protection | Using standard SharedPreferences/UserDefaults for secrets |
| Network Security | Network Security Config XML | App Transport Security in Info.plist | Disabling ATS exceptions without documenting justification |
| Certificate Pinning | OkHttp CertificatePinner / TrustKit | TrustKit / URLSessionDelegate | Pinning leaf certificate instead of SPKI hash |
| Biometric Auth | BiometricPrompt API | LocalAuthentication framework | Storing credentials directly in biometric storage |
| Code Protection | R8/ProGuard obfuscation | LLVM obfuscation + bitcode stripping | Relying solely on obfuscation without runtime checks |
| Device Integrity | Play Integrity API | App Attest + DeviceCheck | Skipping integrity checks on debug builds only |
A critical difference often overlooked is backup behavior. Android allows full app backup by default unless android:allowBackup="false" is set in the manifest. iOS includes Keychain items in encrypted backups but excludes them from unencrypted iTunes backups. Test backup extraction on both platforms during security QA to verify sensitive data does not leak through backup artifacts.
Runtime protection varies by ecosystem
Android's open nature makes runtime manipulation easier. Implement root detection, debugger detection, and emulator detection as layered defenses. iOS sandboxing provides stronger isolation but jailbreak detection remains necessary. Use commercial RASP solutions or open-source alternatives like RootBeer (Android) and JailMonkey (cross-platform) as baseline protections, understanding that determined attackers bypass all client-side checks.
Integrating mobile security into your development workflow
Security controls fail when treated as post-launch hardening. Integrate mobile app security basics into sprint planning, code review, and CI pipelines from day one. Add SAST tools like MobSF or Semgrep to pull request checks. Require security review sign-off for any PR touching authentication, storage, or networking code. Maintain a security decision log documenting why specific controls were chosen over alternatives — this becomes audit evidence and onboarding documentation.
For Nepal-based teams building fintech or health applications, align these controls with NRB directives and local data residency requirements early. Global compliance frameworks map cleanly to local regulations when foundational controls are solid. Budget-conscious startups should prioritize encrypted storage and TLS pinning first; advanced RASP and attestation can follow as threat models mature. Teams already practicing structured observability will find security monitoring integrates naturally — see structured logging best practices for patterns that serve both operational and security telemetry needs.
Next steps for securing your mobile application
Start with a threat model specific to your application's data sensitivity and user base. Implement encrypted storage and certificate pinning before adding features. Test security controls in CI, not just during penetration tests. Document decisions for auditors and future maintainers. If your team needs hands-on guidance implementing these controls or preparing for SOC 2 certification, reach out to discuss your mobile security roadmap. Practical, audit-ready security is achievable without slowing feature delivery when fundamentals are solid.