When handling sensitive data like API keys, tokens, or credentials in Flutter, it's crucial to avoid storing them in plain text. Here are the best approaches:
1. flutter_secure_storage Package
The most common solution is the
flutter_secure_storage package, which uses platform-specific secure storage mechanisms:Implementation:
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
// Create storage instance
final storage = FlutterSecureStorage();
// Write data securely
await storage.write(key: 'api_key', value: 'your_sensitive_data');
// Read data
String? value = await storage.read(key: 'api_key');
// Delete data
await storage.delete(key: 'api_key');
Platform-specific behavior:
- Android: Uses EncryptedSharedPreferences or KeyStore
- iOS: Uses Keychain
- Web: Uses Web Cryptography API or localStorage (less secure)
- Windows/Linux/Mac: Uses libsecret, Keyring, or other platform-specific solutions
2. Encrypted Shared Preferences
For a balance between security and convenience:
import 'package:encrypted_shared_preferences/encrypted_shared_preferences.dart';
final prefs = EncryptedSharedPreferences();
await prefs.setString('token', 'sensitive_value');
String? token = await prefs.getString('token');
3. For Very Sensitive Data: Biometric-protected Storage
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
final storage = FlutterSecureStorage(
aOptions: AndroidOptions(
encryptedSharedPreferences: true,
storageCipherAlgorithm: StorageCipherAlgorithm.AES_CBC_PKCS7Padding,
),
iOptions: IOSOptions(
accessibility: KeychainAccessibility.first_unlock,
),
);
// Write with biometric protection
await storage.write(
key: 'ultra_secure',
value: 'data',
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock_this_device),
aOptions: AndroidOptions(authenticationRequired: true),
);
Best Practices
1. Never hardcode sensitive data in your source code
2. Use environment variables for build-time secrets (with flutter_dotenv)
3. Combine approaches - Use secure storage for runtime secrets and env vars for build-time config
4. Implement auto-delete for temporary tokens
5. Consider backend solutions for extremely sensitive data (have your server handle it)
For API Keys and Build-time Secrets
Use
flutter_dotenv:1. Add to
.env file (add to .gitignore):API_KEY=your_key_here
2. In pubspec.yaml:
dependencies:
flutter_dotenv: ^5.1.0
3. In code:
await dotenv.load(fileName: ".env");
String apiKey = dotenv.env['API_KEY']!;
Remember that no client-side storage is 100% secure, but these methods significantly improve protection against common attacks.


