ESC
Type to search guides, tutorials, and reference documentation.
Verified by Garnet Grid

Mobile App Security

Secure mobile applications against reverse engineering, data theft, network interception, and platform-specific vulnerabilities. Covers certificate pinning, secure storage, biometric authentication, code obfuscation, and the OWASP Mobile Top 10.

Mobile apps run on devices you do not control, on networks you do not trust, and in environments where a determined attacker has physical access. The threat model is fundamentally different from server-side security — the client is hostile territory.


OWASP Mobile Top 10

#RiskMitigation
M1Improper Credential UsageSecure storage, short-lived tokens
M2Inadequate Supply Chain SecurityDependency scanning, SBOMs
M3Insecure Authentication/AuthorizationOAuth 2.0, biometrics, server-side validation
M4Insufficient Input/Output ValidationValidate on client AND server
M5Insecure CommunicationTLS 1.3, certificate pinning
M6Inadequate Privacy ControlsData minimization, encryption at rest
M7Insufficient Binary ProtectionsObfuscation, tamper detection
M8Security MisconfigurationRemove debug flags, secure exports
M9Insecure Data StorageKeychain (iOS), EncryptedSharedPreferences (Android)
M10Insufficient CryptographyPlatform crypto APIs, no custom crypto

Secure Storage

iOS Keychain

import Security

func saveToKeychain(key: String, data: Data) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: key,
        kSecValueData as String: data,
        kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
    ]
    
    SecItemDelete(query as CFDictionary) // Remove existing
    let status = SecItemAdd(query as CFDictionary, nil)
    return status == errSecSuccess
}

Android EncryptedSharedPreferences

val masterKey = MasterKey.Builder(context)
    .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
    .build()

val encryptedPrefs = EncryptedSharedPreferences.create(
    context,
    "secure_prefs",
    masterKey,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

encryptedPrefs.edit().putString("auth_token", token).apply()

Certificate Pinning

// OkHttp certificate pinning
val client = OkHttpClient.Builder()
    .certificatePinner(
        CertificatePinner.Builder()
            .add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
            .add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")
            .build()
    )
    .build()
// URLSession certificate pinning
class PinningDelegate: NSObject, URLSessionDelegate {
    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 serverCertData = SecCertificateCopyData(certificate) as Data
        let pinnedCertData = loadLocalCertificate()
        
        if serverCertData == pinnedCertData {
            completionHandler(.useCredential, URLCredential(trust: serverTrust))
        } else {
            completionHandler(.cancelAuthenticationChallenge, nil)
        }
    }
}

Biometric Authentication

// iOS Face ID / Touch ID
import LocalAuthentication

func authenticateWithBiometrics(completion: @escaping (Bool) -> Void) {
    let context = LAContext()
    var error: NSError?
    
    guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
        completion(false)
        return
    }
    
    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
                          localizedReason: "Authenticate to access your account") { success, error in
        DispatchQueue.main.async { completion(success) }
    }
}

Anti-Patterns

Anti-PatternConsequenceFix
Secrets in code/strings.xmlExtracted by decompilationServer-side secrets, obfuscation
HTTP for any API callsNetwork interceptionTLS everywhere + certificate pinning
Storing tokens in plain SharedPrefsExtracted from rooted devicesKeychain / EncryptedSharedPreferences
No code obfuscation (Android)Easy reverse engineeringProGuard / R8 obfuscation
Logging sensitive dataVisible in logcat / device consoleStrip logs in release builds

Mobile security is defense in depth. No single measure is sufficient. Layer secure storage, encrypted communication, certificate pinning, biometric authentication, and server-side validation to protect user data on hostile devices.

Jakub Dimitri Rezayev
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting

Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.

View Full Profile →