flutter_secure_storage
flutter_secure_storage copied to clipboard
PlatformException: Code: -25308. Help me!
On a beautiful day, I received this token, and it seems that it caused my app to crash. To be more precise, I tried to catch the error, so it didn't take the main key, causing the session to log out. I am using it to encrypt the Hive NoSQL database.
my code using it
// Create key and encryption
FlutterSecureStorage secureStorage = const FlutterSecureStorage();
String? secureStorageKey;
late List<int> encryptionKey;
String storeKey = AppConfig.storeKey(isDev: F.appFlavor == Flavor.beta);
/** @see: https://github.com/mogol/flutter_secure_storage/issues/84*/
try {
secureStorageKey = await secureStorage.read(key: storeKey);
Helpers.dump('secureStorageKey value: $secureStorageKey', line: true);
} catch (ex, stackTrace) {
Helpers.reportSentry(ex, stackTrace);
await secureStorage.delete(key: storeKey);
}
if ((secureStorageKey?.isEmpty ?? true)) {
await secureStorage.delete(key: storeKey);
var key = Hive.generateSecureKey();
Helpers.dump('Before Write Key value: $key', line: true);
Helpers.dump('Before Write secureStorageKey value: ${base64UrlEncode(key)}', line: true);
await secureStorage.write(
key: storeKey,
value: base64UrlEncode(key),
);
Helpers.dump('Write success key: $key', line: true);
encryptionKey = key;
}else{
secureStorageKey = await secureStorage.read(key: storeKey);
encryptionKey = base64Url.decode(secureStorageKey ?? '');
}
Helpers.dump('Encryption key: $encryptionKey', line: true);
//Open Boxes
await Hive.openBox<UserHiveModel>(UserHiveModel.boxKey, encryptionCipher: HiveAesCipher(encryptionKey));
await Hive.openBox<SettingHiveModel>(SettingHiveModel.boxKey, encryptionCipher: HiveAesCipher(encryptionKey));
await Hive.openBox<GeotrackHiveModel>(GeotrackHiveModel.boxKey, encryptionCipher: HiveAesCipher(encryptionKey));
await Hive.openBox<MAccessTokenHive>(MAccessTokenHive.boxKey, encryptionCipher: HiveAesCipher(encryptionKey));
await Hive.openBox<ProjectHiveModel>(ProjectHiveModel.boxKey, encryptionCipher: HiveAesCipher(encryptionKey));
await Hive.openBox<ActionPostHiveModel>(ActionPostHiveModel.boxKey, encryptionCipher: HiveAesCipher(encryptionKey));
await Hive.openBox<PostHiveModel>(PostHiveModel.boxKey, encryptionCipher: HiveAesCipher(encryptionKey));
await Hive.openBox<MediaHiveModel>(MediaHiveModel.boxKey, encryptionCipher: HiveAesCipher(encryptionKey));
Error -25308 is errSecInteractionNotAllowed.
You might want to read this post on the Apple Developer Forums.
Can you give us some more context, i.e. the OS, version etc.?
@techouse Oke. Project using :
- FLutter: 3.22.0
- flutter_secure_storage: ^9.2.2
- Device: Iphone 11 Pro(arm64) x IOS(v17.4.1)
facing the same issue
flutter version: 3.19.3 flutter_secure_storage: 9.2.2
@gamestap99 Can you replicate this on a simulator or provide us with some sample code that replicates this error?
Does it work with v9.0.0 using something like this?
dependency_overrides:
flutter_secure_storage: 9.0.0
flutter_secure_storage_linux: 1.2.0
flutter_secure_storage_macos: 3.0.1
flutter_secure_storage_platform_interface: 1.0.2
flutter_secure_storage_windows: 3.0.0
flutter_secure_storage_web: 1.2.0
Facing the Same Issue
FLutter: 3.22.0
flutter_secure_storage: ^9.2.1
Device: Iphone 15 Pro IOS(v17.4.1)
Same issue for one customer, bug not always flutter_secure_storage: 9.2.2 iOS 16.7.8
Same issue for some customers, bug not always, after read data when device was unlocked flutter_secure_storage: 9.2.2
iOS 17.5.1 - 43,75 % iOS 17.4.1- 31,25 % iOS 16.5 - 25 %
This issue is replicable by reading from a secure storage(keychain) when a device is locked and has a passcode.
It can be fixed with:
final _storageProvider = FlutterSecureStorage(
iOptions: IOSOptions.defaultOptions.copyWith(
accessibility: KeychainAccessibility.first_unlock_this_device,
synchronizable: true,
),
);
Note:
Without providing synchronizable: true it throws the errSecDuplicateItem platform exception for me.
Issue disappeared when I downgraded the library:
dependency_overrides:
# Downgrade secure storage to 9.0.0 as version 9.2.2 has introduced some crashes on iOS
# The error description is "Unexpected security result code, Code: -25308"
flutter_secure_storage: 9.0.0
flutter_secure_storage_linux: 1.2.0
flutter_secure_storage_macos: 3.0.1
flutter_secure_storage_platform_interface: 1.0.2
flutter_secure_storage_web: 1.1.2
flutter_secure_storage_windows: 3.0.0
This issue is replicable by reading from a secure storage(keychain) when a device is locked and has a passcode.
It can be fixed with:
final _storageProvider = FlutterSecureStorage( iOptions: IOSOptions.defaultOptions.copyWith( accessibility: KeychainAccessibility.first_unlock_this_device, synchronizable: true, ), );Note: Without providing
synchronizable: trueit throws theerrSecDuplicateItemplatform exception for me.
What are the consequences of doing this?
This issue is replicable by reading from a secure storage(keychain) when a device is locked and has a passcode. It can be fixed with:
final _storageProvider = FlutterSecureStorage( iOptions: IOSOptions.defaultOptions.copyWith( accessibility: KeychainAccessibility.first_unlock_this_device, synchronizable: true, ), );Note: Without providing
synchronizable: trueit throws theerrSecDuplicateItemplatform exception for me.What are the consequences of doing this?
https://developer.apple.com/documentation/security/ksecattraccessibleafterfirstunlock
@mogol, please, can you explain why this happens and can it be fixed by someone?
We are also getting that crash after upgrading to the v9.2.2 version.
Facing same issue on latest version.
Facing same issue as well on latest version for some iOS devices with the options fix set.
IOSOptions _getIOSOptions() => const IOSOptions( accessibility: KeychainAccessibility.first_unlock, synchronizable: true, accountName: 'myapp_prefs', );
await _secureStorage.write(key: newItem.key.name, value: newItem.value, aOptions: _getAndroidOptions(), iOptions: _getIOSOptions());
Having the same issue with this initialization but only in release mode in my live app :
final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(
aOptions: AndroidOptions(
encryptedSharedPreferences: true,
),
iOptions: IOSOptions(synchronizable: false)
);
I changed my usage from
final storage = const FlutterSecureStorage(aOptions: AndroidOptions(encryptedSharedPreferences: true));
to
final _storage = const FlutterSecureStorage(
aOptions: AndroidOptions(encryptedSharedPreferences: true),
iOptions: IOSOptions(
accessibility: KeychainAccessibility.first_unlock_this_device,
synchronizable: true,
),
);
Seems the problem didn't happen but behaved values aren't stored anymore before!
Seems the problem didn't happen but behaved values aren't stored anymore before!
When changing the settings, you need to "migrate" values from the previous settings. I described this in a similar issue.
Seems the problem didn't happen but behaved values aren't stored anymore before!
When changing the settings, you need to "migrate" values from the previous settings. I described this in a similar issue.
I've just reviewed your metod, it simply uses secure storage first, then uses legacy (shared prefs imho) if secure storage fails. This means same values are stored (must be stored) in secure storage and legacy options both, otherwise this fallback does not work.
In my scenario,
- App is terminated and device is locked.
- App receives video call on lock screen and user accepts it.
- App starts and gets user credentials from secure storage. -----> Here booms
To make work your scenario i would be storing those credentials in "legacy" option too :/
I've just reviewed your metod, it simply uses secure storage first, then uses legacy (shared prefs imho) if secure storage fails. This means same values are stored (must be stored) in secure storage and legacy options both, otherwise this fallback does not work.
No, it's using secure storage in both cases. "Legacy" refers to the secure storage being created/accessed with the old settings. Here's the associated code:
Yes, my mistake. Both storages are indeed FlutterSecureStorage.
Based on your latest post, it looks like _legacyStorage is the one I’ve already been using, and it’s throwing the 25308 exception.
I also tried _storage (as I mentioned in my first post), but it returns empty for all my keys.
To sum up, using _storage first and getting an empty result, then trying _legacyStorage and getting the 25308 exception, doesn't add up. How would this resolve the issue?
Yes, my mistake. Both storages are indeed FlutterSecureStorage.
Based on your latest post, it looks like
_legacyStorageis the one I’ve already been using, and it’s throwing the 25308 exception.I also tried
_storage(as I mentioned in my first post), but it returns empty for all my keys.To sum up, using
_storagefirst and getting an empty result, then trying_legacyStorageand getting the 25308 exception, doesn't add up. How would this resolve the issue?
In my case, if the app was restarted, the storage was accessible again...It was reading from the background that was messing things up. If in your case the "legacy" storage is fully borked and you can no longer read from it, migration may not be possible.
The error is due to data being requested while it is not allowed to, defined via accessibility: KeychainAccessibility....
If you want to read data while the app is in the background, please change the accessibility parameter to the correct setting.
The error is due to data being requested while it is not allowed to, defined via
accessibility: KeychainAccessibility....If you want to read data while the app is in the background, please change the accessibility parameter to the correct setting.
Hi there, which parameter do we have to use then? (in case we want to access the keychain in the background + screen locked)
Using first_unlock or first_unlock_this_device the item will become available after the first unlock (when the device is booted), so it will always be accessible if locked after first unlock.
See https://github.com/juliansteenbakker/flutter_secure_storage/blob/97fbb0eb766aaf818e91bca5d71e702589545945/flutter_secure_storage/lib/options/apple_options.dart#L24
And https://developer.apple.com/documentation/security/item-attribute-keys-and-values#Accessibility-Values
Using
first_unlockorfirst_unlock_this_devicethe item will become available after the first unlock (when the device is booted), so it will always be accessible if locked after first unlock. Seeflutter_secure_storage/flutter_secure_storage/lib/options/apple_options.dart
Line 24 in 97fbb0e
first_unlock, And https://developer.apple.com/documentation/security/item-attribute-keys-and-values#Accessibility-Values
Perfect, thank you! Another question: is it mandatory to reinstall the app to apply the new first_unlock configuration?
I have this behaviour: I have a ping timer running in the background that requires authentication. In case the access token has expired, a new one is requested, but to do that, I need to access the secure storage once. For some reason, with first_unlock option I still have the behavior where it throws the PlatformException.
This behaviour is not there when I reinstall the app.
i am getting this isue after adding first unlock PlatformException(Unexpected security result code, Code: -25299, Message: The specified item already exists in the keychain., -25299, null).
@juliansteenbakker