Skip to content
AgileLogics
6 min read

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.