Summary
The secure storage documentation is missing several platform-specific behaviors that cause data loss, unexpected data exposure, or silent failures in production apps:
- Android: backup restoration corrupts secure storage — encrypted values backed up via Auto Backup cannot be decrypted on a new device (encryption keys don't transfer), causing exceptions on every
GetAsync call after restore
- iOS: Keychain entries persist after app uninstall — unlike Android, uninstalling an iOS app does not clear its Keychain entries; values survive reinstall
- iOS: Keychain entries can sync via iCloud — if the user has iCloud Keychain enabled, secure storage values may silently appear on other devices
- Windows: 64 KB total composite storage limit — not documented; exceeding it fails silently or throws
Why it matters
Each of these causes real production incidents:
-
Android backup corruption is the most impactful: after a user restores their phone to a new device, every GetAsync call throws an exception. Apps that don't wrap secure storage in try/catch crash on launch. The fix (disabling backup or excluding the secure storage preference file) requires manifest changes that aren't mentioned in the docs.
-
iOS Keychain persistence after uninstall causes a security issue: if a user sells their device and a new user installs the same app, the new user can access the previous user's stored tokens. The fix (clearing Keychain on first launch using a UserDefaults flag) is a known pattern but not documented.
-
iOS iCloud sync means a token stored on one device can appear on another — a surprising behavior for data the developer considers device-local.
What should be documented
Android: Handle Auto Backup to prevent restore corruption
Warning: Android Auto Backup can back up and restore SecureStorage values to a new device where the original encryption key no longer exists. This causes GetAsync to throw on every call after restore. Always handle this exception and clear corrupted values:
try
{
var value = await SecureStorage.Default.GetAsync("auth_token");
}
catch (Exception)
{
// Encrypted value from backup cannot be decrypted — clear all secure values
SecureStorage.Default.RemoveAll();
}
To prevent the issue, exclude SecureStorage from Auto Backup in AndroidManifest.xml:
<application android:fullBackupContent="@xml/auto_backup_rules" ...>
With Platforms/Android/Resources/xml/auto_backup_rules.xml:
<full-backup-content>
<exclude domain="sharedpref"
path="${applicationId}.microsoft.maui.essentials.preferences.xml" />
</full-backup-content>
iOS: Keychain does not clear on uninstall
Note: Unlike Android, uninstalling an iOS app does not remove its Keychain entries. If the app is reinstalled, previously stored values are still accessible. To avoid exposing one user's stored data to another, check for a "first launch" flag and clear Keychain entries if this is a fresh install:
if (!Preferences.Default.ContainsKey("app_initialized"))
{
SecureStorage.Default.RemoveAll();
Preferences.Default.Set("app_initialized", true);
}
iOS: iCloud Keychain sync
Note: If the device user has iCloud Keychain enabled, Keychain values (including those written by SecureStorage) may sync to the user's other Apple devices. This is not controllable from .NET MAUI. If device-local isolation is required, consider this behavior when deciding what data to store in SecureStorage.
Windows: storage size limits
Windows limits: SecureStorage on Windows stores values in ApplicationData. The key name maximum is 255 characters, individual values are limited to 8 KB, and the composite storage total is limited to 64 KB. Exceeding these limits throws. Store only short string values (tokens, keys) — not binary data or large serialized objects.
Suggested location
docs/platform-integration/storage/secure-storage.md — add a "Platform-specific behavior" section with per-platform callouts for each of the above
Summary
The secure storage documentation is missing several platform-specific behaviors that cause data loss, unexpected data exposure, or silent failures in production apps:
GetAsynccall after restoreWhy it matters
Each of these causes real production incidents:
Android backup corruption is the most impactful: after a user restores their phone to a new device, every
GetAsynccall throws an exception. Apps that don't wrap secure storage in try/catch crash on launch. The fix (disabling backup or excluding the secure storage preference file) requires manifest changes that aren't mentioned in the docs.iOS Keychain persistence after uninstall causes a security issue: if a user sells their device and a new user installs the same app, the new user can access the previous user's stored tokens. The fix (clearing Keychain on first launch using a
UserDefaultsflag) is a known pattern but not documented.iOS iCloud sync means a token stored on one device can appear on another — a surprising behavior for data the developer considers device-local.
What should be documented
Android: Handle Auto Backup to prevent restore corruption
To prevent the issue, exclude SecureStorage from Auto Backup in
AndroidManifest.xml:With
Platforms/Android/Resources/xml/auto_backup_rules.xml:iOS: Keychain does not clear on uninstall
iOS: iCloud Keychain sync
Windows: storage size limits
Suggested location
docs/platform-integration/storage/secure-storage.md— add a "Platform-specific behavior" section with per-platform callouts for each of the above