Security cheat sheet
The 9 Security interview answers in 30 seconds each, plus quick facts. Printable, free.
One page per topic: print it or save it as PDF from your browser's print menu. Practise these questions
Rules of thumb
- Keys live in Keystore; data lives encrypted in private storage.
- Nothing in the APK is secret.
- Bind biometrics to a CryptoObject.
- Export only what must be public; validate every extra.
- Verify Play Integrity tokens on the server.
Storing tokens and secrets on device
Keep secrets in app-private storage (DataStore or a file) encrypted with a key from the Android Keystore, so the key never leaves secure hardware. Jetpack Security's EncryptedSharedPreferences is now deprecated, so new code uses Keystore directly or a library like Tink. Never put secrets in external storage, logs, or plain SharedPreferences, and exclude them from backups.
Android Keystore
The Keystore system lets apps create cryptographic keys that can't be exported. Operations run inside a trusted environment (TEE) or a separate secure chip (StrongBox) when available, so even if an attacker gets app files, they can't copy the key. You can require user authentication, an unlocked device, or a specific purpose (encrypt, sign) for each key.
fun encrypt(key: javax.crypto.SecretKey, plain: ByteArray): Pair<ByteArray, ByteArray> {
val cipher = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, key)
return cipher.iv to cipher.doFinal(plain)
}Biometric authentication
Use BiometricPrompt from androidx.biometric. For real security, bind it to a crypto operation: create a Keystore key that requires authentication, pass a CryptoObject with a cipher to the prompt, and use the unlocked cipher only after success. A prompt that just returns 'success' without crypto can be bypassed on a compromised device.
Network security config and pinning
network_security_config.xml sets per-domain rules: whether cleartext HTTP is allowed (blocked by default when targeting API 28+), which certificate authorities to trust (user-added CAs aren't trusted by default when targeting API 24+), debug-only overrides, and pins. Pinning protects against mis-issued certificates but can lock users out if certificates rotate, so pin public keys, include a backup pin, and set an expiration.
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">api.example.com</domain>
<pin-set expiration="2027-06-01">
<pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
<pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
</pin-set>
</domain-config>
<debug-overrides>
<trust-anchors><certificates src="user" /></trust-anchors>
</debug-overrides>
</network-security-config>Exported components and intent safety
An exported Activity, Service, receiver or provider can be started by any app. Since Android 12, components with intent filters must declare android:exported explicitly. Export only what must be public, protect the rest with exported="false" or a signature permission, validate every extra from incoming intents, and never forward an untrusted intent (intent redirection).
WebView security
WebView runs web content inside your app. Risks: JavaScript bridges (addJavascriptInterface) exposing app functions to any loaded page, file access letting pages read local files, loading untrusted URLs, and mixed content. Enable JavaScript only when needed, load only trusted origins, use WebViewAssetLoader for local content instead of file URLs, and keep Safe Browsing on.
API keys and secrets in the APK
No. Anything shipped in the APK, including BuildConfig fields, resources, native libraries and obfuscated strings, can be extracted. Keep real secrets on your server and have the app call your backend, which calls the third party. For keys that must ship, such as maps keys, restrict them by package name and signing certificate and set quotas.
Play Integrity API
Play Integrity lets your server check that a request comes from your genuine app, installed from Google Play, on a genuine certified Android device. The app requests a token and sends it to your backend, which has Google decrypt and verify it, then decides. It replaced the SafetyNet Attestation API, which has been shut down. Use verdicts as risk signals, not a hard block for every user.
Least privilege and privacy APIs
Ask only for what a feature needs, at the moment it's used. Prefer privacy-friendly alternatives: the Photo Picker instead of storage permissions, approximate location when precise isn't needed, Activity Result contracts like TakePicture that need no camera permission, and Credential Manager instead of reading accounts. Audit merged manifests, since libraries can add permissions.
Quick facts
- StrongBox
- StrongBox is a Keystore backed by a separate secure chip, available on some devices since Android 9.
- Cleartext default
- Apps targeting API 28 or higher block cleartext HTTP by default.
- User CAs
- Apps targeting API 24 or higher don't trust user-installed certificate authorities by default.
- SafetyNet
- The SafetyNet Attestation API was shut down; Play Integrity replaced it.