KeroJohn97
KeroJohn97

Reputation: 362

Flutter Secure Storage Issues: Unable to read or write keys and values

I am using this package to store some login credentials in a Flutter mobile application. The version I use is v5.0.2. I am not sure if I am storing or reading the value in the correct way. Does anyone know how to check it, or what am I missing or doing wrong.

import 'package:flutter_secure_storage/flutter_secure_storage.dart';

class SecureStorage {
  final _storage = const FlutterSecureStorage();

  Future<Map<String, String>> _readAll() async {
    return await _storage.readAll(
        iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
  }

  void deleteAll() async {
    await _storage.deleteAll(
        iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    _readAll();
  }

  Future<String?> readSecureData(String key) async {
    return await _storage.read(key: key);
  }

  Future<void> deleteSecureData(String key) async {
    return await _storage.delete(key: key);
  }

  void writeSecureData(String key, String value) async {
    await _storage.write(
      key: key,
      value: value,
      iOptions: _getIOSOptions(),
      aOptions: _getAndroidOptions(),
    );
  }

  IOSOptions _getIOSOptions() => const IOSOptions(
        accessibility: IOSAccessibility.first_unlock,
      );

  AndroidOptions _getAndroidOptions() => const AndroidOptions(
        encryptedSharedPreferences: true,
      );
}

final secureStorage = SecureStorage();

This is how I called the value,

@override
  void initState() {
    Future.delayed(Duration.zero, () async {
      final username = await secureStorage.readSecureData('username') ?? '';
      final password = await secureStorage.readSecureData('password') ?? '';
      setState(() {
        _icNoController.text = username;
        _passwordController.text = password;
      });
    });
    super.initState();
  }

And this is how I stored the value,

await secureStorage.writeSecureData('username', username);
await secureStorage.writeSecureData('password', password);

Upvotes: 3

Views: 15504

Answers (3)

Em&#237;lio Nicoletti
Em&#237;lio Nicoletti

Reputation: 21

Once you are using const in your getters, I think maybe it will be better if you just throw the const options into the FlutterSecureStorage constructor , like:

final _storage = const FlutterSecureStorage(
  iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
  aOptions: AndroidOptions(encryptedSharedPreferences: true),
);

Upvotes: 2

paj-co
paj-co

Reputation: 138

I think the reason for reading / writing problem can be inconsistency with using aOptions or iOptions.

For ex. you are using aOptions with readAll(), deleateAll() and write() methods and you don't use it with read(), delete().

So, when using encryptedSharedPreferences: true, in aOptions when you write data to secure storage, you specify that this data must be written to EncryptedSharedPreferences.

However when you read the data without providing aOptions again, you try to read from default secure storage which is not the EncryptedSharedPreferences where you have stored the data. Example with aOptions is for Android, I haven't tested this library on iOS yet.

Upvotes: 6

Roslan Amir
Roslan Amir

Reputation: 1336

I have cleaned up the class for you:

class SecureStorage {
  const _storage = FlutterSecureStorage();

  Future<Map<String, String>> _readAll() async {
    var map = <String, String>{};
    try {
      map = await _storage.readAll(
        iOptions: _getIOSOptions(),
        aOptions: _getAndroidOptions(),
      );
    } catch (e) {
      print(e);
    }
    return map;
  }

  Future<void> deleteAll() async {
    try {
      await _storage.deleteAll(
        iOptions: _getIOSOptions(),
        aOptions: _getAndroidOptions(),
      );
      // _readAll();
    } catch (e) {
      print(e);
    }
  }

  Future<String> readSecureData(String key) async {
    String value = "";
    try {
      value = (await _storage.read(key: key)) ?? "";
    } catch (e) {
      print(e);
    }
    return value;
  }

  Future<void> deleteSecureData(String key) async {
    try {
      await _storage.delete(key: key);
    } catch (e) {
      print(e);
    }
  }

  Future<void> writeSecureData(String key, String value) async {
    try {
      await _storage.write(
        key: key,
        value: value,
        iOptions: _getIOSOptions(),
        aOptions: _getAndroidOptions(),
      );
    } catch (e) {
      print(e);
    }
  }

  IOSOptions _getIOSOptions() => const IOSOptions(
    accessibility: IOSAccessibility.first_unlock,
  );

  AndroidOptions _getAndroidOptions() => const AndroidOptions(
    encryptedSharedPreferences: true,
  );
}

Of course, I use a Logger package instead of print. Also I don't understand why you do a _readAll after deleteAll.

ANSWERS

Q. "I am not sure if I am storing or reading the value in the correct way."

A. The correct way to store and read the values are by wrapping them in a try-catch block, as illustrated the code above.

Q. "Does anyone know how to check it, or what am I missing or doing wrong."

A. See the code above for example of how to do it the right way which I personally found works for me.

Upvotes: 1

Related Questions