Security Fundamentals
Prerequisites: Making HTTP requests, State management
Apps handle personal data and credentials, and they run on devices you don't control. A few practices cover most of the risk.
1. Don't ship secrets
Anything inside an app — API keys, passwords, private URLs — can be extracted by anyone who downloads it, even from AOT-compiled code. Keep truly secret keys on your server, and have the app authenticate to the server with per-user tokens.
Build-time configuration such as
--dart-define=API_URL=https://api.example.com is fine for settings, but
it is not a way to hide secrets.
2. Store tokens securely
Store auth tokens with the flutter_secure_storage package, which
uses the iOS Keychain and Android's Keystore-backed encryption — not in
shared_preferences, which is stored in plain text.
3. Secure randomness
Use Random.secure() for anything security-related — tokens, IDs that
must be unguessable, passwords:
import 'dart:convert';
import 'dart:math';
void main() {
final random = Random.secure();
final bytes = List<int>.generate(24, (_) => random.nextInt(256));
final token = base64Url.encode(bytes);
print(token.length);
}
32
A plain Random() is predictable and must never be used for security.
For hashing and cryptography, use the well-reviewed crypto and
cryptography packages rather than writing your own algorithms.
4. Network security
- Use HTTPS only. Android and iOS block plain HTTP by default for new apps — keep it that way.
- For high-risk apps, consider certificate pinning, which rejects servers presenting unexpected certificates.
5. Validate on the server
Anything in a request can be changed by the sender, even if it came from your own app. The server must validate input and check permissions on every request; client-side validation is only for user convenience. On a Dart server, use parameterized database queries — never build SQL by inserting user input into a string.
6. Privacy and permissions
- Request permissions (camera, location, contacts) only when the feature needs them, with a clear explanation.
- Declare collected data accurately in App Store privacy details and Google Play's Data safety form.
- Don't log tokens or personal data.
7. Dependencies
Packages run with your app's full permissions. Prefer well-maintained
packages, keep them updated (dart pub outdated), and review what a
package does before adding it.
Obfuscation
flutter build --obfuscate --split-debug-info=build/symbols makes
reverse engineering harder — useful, but never a substitute for keeping
secrets off the device.