Securing Your Data Locally with Flutter
Why Local Storage Matters
You might wonder why we need local storage when we can save data on a server. But what if you need data in your app in offline mode? You don’t want to show the “No Connectivity” warning to your end users, which is why local storage is essential.
Introducing Flutter Secure Storage
Flutter Secure Storage is a Flutter plugin used to store data in secure storage. But what makes it secure? The description of secure storage changes depending on the platform.
- For Android, it stores data in encryptedSharedPreferences, which encrypts keys and values using AES encryption.
- For iOS, it uses the KeyChain, an iOS-specific secure storage for storing and accessing cryptographic keys.
- On the web, it utilizes the Web Cryptography (Web Crypto) API.
Getting Started with Local Storage Demo
To get started, download the starter project containing the prebuilt UI and minimal configuration. Open it in your editor, build, and run the app. The file structure looks like this:
main.dart: the entry point for the whole app
home_view.dart: contains the Home view where the secured data list will be displayed
storage_service.dart: contains methods responsible for reading, writing, and deleting data from secured storage
storage_item.dart: the model or state to store data in a key-value pair
widgets: directory containing additional custom widgets to help build the UI
Setting Up Secure Storage
To set up secure storage, add the fluttersecurestorage package to your pubspec dependencies.
For Android, update the minSdkVersion in your project-level build.gradle file:
android {
...
defaultConfig {
...
minSdkVersion 21
...
}
}
For web, enable HTTP Strict-Transport-Security (HSTS) and other important HTTP security headers.
For Linux, use Flutter’s manual installation and ensure libsecret-1-dev and libjsoncpp-dev are installed on your machine.
Secure Storage Methods
Create a class with methods to read, write, and delete data from secure storage. Initialize an instance of FlutterSecureStorage() and create methods for writing, reading, deleting, and checking if a key exists in secure storage:
class StorageService {
final FlutterSecureStorage _storage;
StorageService() : _storage = const FlutterSecureStorage();
Future<void> writeSecureData(String key, String value) async {
await _storage.write(key: key, value: value);
}
Future<String> readSecureData(String key) async {
return await _storage.read(key: key);
}
Future<void> deleteSecureData(String key) async {
await _storage.delete(key: key);
}
Future<bool> containsKeyInSecureStorage(String key) async {
return await _storage.containsKey(key: key);
}
}
Using Secure Storage in Your Flutter App
Update the starter project to utilize the above methods. Read all the data present in the storage and display it in the UI:
Future<void> _readAllSecureData() async {
final List<StorageItem> storageItems = [];
final keys = await _storage.getKeys();
for (final key in keys) {
final value = await _storage.read(key: key);
storageItems.add(StorageItem(key: key, value: value));
}
setState(() {
_storageItems = storageItems;
});
}
Write new data by creating a new StorageItem object and using the writeSecureData method:
Future<void> _writeSecureData() async {
final StorageItem storageItem = StorageItem(key: 'new_key', value: 'new_value');
await _storage.writeSecureData(storageItem.key, storageItem.value);
}
Delete data by using the deleteSecureData method:
Future<void> _deleteSecureData(String key) async {
await _storage.deleteSecureData(key);
}
Search for existing data by using the readSecureData method and passing the key:
Future<String> _readSecureData(String key) async {
return await _storage.readSecureData(key);
}
Deleting All Data and Editing Storage Items
Delete all data by using the deleteAllSecureData method:
Future<void> _deleteAllSecureData() async {
await _storage.deleteAll();
}
Edit existing data by updating the VaultCard widget and using the writeSecureData method:
Future<void> _editSecureData(String key, String newValue) async {
await _storage.writeSecureData(key, newValue);
}
Alternatives to Flutter Secure Storage
There are more databases providing encryption and decryption of data to your Flutter app. Some alternatives include:
- SQFlite with SQLCipher support
- Sembast
- Hive
- Drift
Each alternative has its own strengths and weaknesses, so choose the one that suits your requirements best.