mirror of
https://github.com/bitwarden/mobile
synced 2025-12-15 15:53:44 +00:00
[PM-1817] Expand biometric integrity checks to the account level (#2498)
* Change bio integrity validation to work at account-level * biometric state migration * fix account bio valid key storage location during migration * comment clarification * fix for iOS extensions not using custom avatar color
This commit is contained in:
@@ -13,8 +13,9 @@ namespace Bit.Core.Services
|
||||
{
|
||||
public class StateMigrationService : IStateMigrationService
|
||||
{
|
||||
private const int StateVersion = 4;
|
||||
private const int StateVersion = 5;
|
||||
|
||||
private readonly DeviceType _deviceType;
|
||||
private readonly IStorageService _preferencesStorageService;
|
||||
private readonly IStorageService _liteDbStorageService;
|
||||
private readonly IStorageService _secureStorageService;
|
||||
@@ -27,9 +28,10 @@ namespace Bit.Core.Services
|
||||
Secure,
|
||||
}
|
||||
|
||||
public StateMigrationService(IStorageService liteDbStorageService, IStorageService preferenceStorageService,
|
||||
IStorageService secureStorageService)
|
||||
public StateMigrationService(DeviceType deviceType, IStorageService liteDbStorageService,
|
||||
IStorageService preferenceStorageService, IStorageService secureStorageService)
|
||||
{
|
||||
_deviceType = deviceType;
|
||||
_liteDbStorageService = liteDbStorageService;
|
||||
_preferencesStorageService = preferenceStorageService;
|
||||
_secureStorageService = secureStorageService;
|
||||
@@ -79,6 +81,9 @@ namespace Bit.Core.Services
|
||||
case 3:
|
||||
await MigrateFrom3To4Async();
|
||||
break;
|
||||
case 4:
|
||||
await MigrateFrom4To5Async();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,6 +447,10 @@ namespace Bit.Core.Services
|
||||
// Removal of old state data will happen organically as state is rebuilt in app
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region v4 to v5 Migration
|
||||
|
||||
private class V4Keys
|
||||
{
|
||||
internal static string VaultTimeoutKey(string userId) => $"vaultTimeout_{userId}";
|
||||
@@ -450,6 +459,87 @@ namespace Bit.Core.Services
|
||||
internal const string ThemeKey = "theme";
|
||||
internal const string AutoDarkThemeKey = "autoDarkTheme";
|
||||
internal const string DisableFaviconKey = "disableFavicon";
|
||||
internal const string BiometricIntegrityKey = "biometricIntegrityState";
|
||||
internal const string iOSAutoFillBiometricIntegrityKey = "iOSAutoFillBiometricIntegrityState";
|
||||
internal const string iOSExtensionBiometricIntegrityKey = "iOSExtensionBiometricIntegrityState";
|
||||
internal const string iOSShareExtensionBiometricIntegrityKey = "iOSShareExtensionBiometricIntegrityState";
|
||||
}
|
||||
|
||||
private async Task MigrateFrom4To5Async()
|
||||
{
|
||||
var bioIntegrityState = await GetValueAsync<string>(Storage.Prefs, V4Keys.BiometricIntegrityKey);
|
||||
var iOSAutofillBioIntegrityState =
|
||||
await GetValueAsync<string>(Storage.Prefs, V4Keys.iOSAutoFillBiometricIntegrityKey);
|
||||
var iOSExtensionBioIntegrityState =
|
||||
await GetValueAsync<string>(Storage.Prefs, V4Keys.iOSExtensionBiometricIntegrityKey);
|
||||
var iOSShareExtensionBioIntegrityState =
|
||||
await GetValueAsync<string>(Storage.Prefs, V4Keys.iOSShareExtensionBiometricIntegrityKey);
|
||||
|
||||
if (_deviceType == DeviceType.Android && string.IsNullOrWhiteSpace(bioIntegrityState))
|
||||
{
|
||||
bioIntegrityState = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
await SetValueAsync(Storage.Prefs, V5Keys.BiometricIntegritySourceKey, bioIntegrityState);
|
||||
|
||||
if (_deviceType == DeviceType.iOS)
|
||||
{
|
||||
await SetValueAsync(Storage.Prefs, V5Keys.iOSAutoFillBiometricIntegritySourceKey,
|
||||
iOSAutofillBioIntegrityState);
|
||||
await SetValueAsync(Storage.Prefs, V5Keys.iOSExtensionBiometricIntegritySourceKey,
|
||||
iOSExtensionBioIntegrityState);
|
||||
await SetValueAsync(Storage.Prefs, V5Keys.iOSShareExtensionBiometricIntegritySourceKey,
|
||||
iOSShareExtensionBioIntegrityState);
|
||||
}
|
||||
|
||||
var state = await GetValueAsync<State>(Storage.LiteDb, Constants.StateKey);
|
||||
if (state?.Accounts is null)
|
||||
{
|
||||
// No accounts available, update stored version and exit
|
||||
await SetLastStateVersionAsync(5);
|
||||
return;
|
||||
}
|
||||
|
||||
// build integrity keys for existing users
|
||||
foreach (var account in state.Accounts.Where(a => a.Value?.Profile?.UserId != null))
|
||||
{
|
||||
var userId = account.Value.Profile.UserId;
|
||||
|
||||
await SetValueAsync(Storage.LiteDb,
|
||||
V5Keys.AccountBiometricIntegrityValidKey(userId, bioIntegrityState), true);
|
||||
|
||||
if (_deviceType == DeviceType.iOS)
|
||||
{
|
||||
await SetValueAsync(Storage.LiteDb,
|
||||
V5Keys.AccountBiometricIntegrityValidKey(userId, iOSAutofillBioIntegrityState), true);
|
||||
await SetValueAsync(Storage.LiteDb,
|
||||
V5Keys.AccountBiometricIntegrityValidKey(userId, iOSExtensionBioIntegrityState), true);
|
||||
await SetValueAsync(Storage.LiteDb,
|
||||
V5Keys.AccountBiometricIntegrityValidKey(userId, iOSShareExtensionBioIntegrityState), true);
|
||||
}
|
||||
}
|
||||
|
||||
// Update stored version
|
||||
await SetLastStateVersionAsync(5);
|
||||
|
||||
// Remove old data
|
||||
await RemoveValueAsync(Storage.Prefs, V4Keys.BiometricIntegrityKey);
|
||||
await RemoveValueAsync(Storage.Prefs, V4Keys.iOSAutoFillBiometricIntegrityKey);
|
||||
await RemoveValueAsync(Storage.Prefs, V4Keys.iOSExtensionBiometricIntegrityKey);
|
||||
await RemoveValueAsync(Storage.Prefs, V4Keys.iOSShareExtensionBiometricIntegrityKey);
|
||||
}
|
||||
|
||||
private class V5Keys
|
||||
{
|
||||
internal const string BiometricIntegritySourceKey = "biometricIntegritySource";
|
||||
internal const string iOSAutoFillBiometricIntegritySourceKey = "iOSAutoFillBiometricIntegritySource";
|
||||
internal const string iOSExtensionBiometricIntegritySourceKey = "iOSExtensionBiometricIntegritySource";
|
||||
|
||||
internal const string iOSShareExtensionBiometricIntegritySourceKey =
|
||||
"iOSShareExtensionBiometricIntegritySource";
|
||||
|
||||
internal static string AccountBiometricIntegrityValidKey(string userId, string systemBioIntegrityState) =>
|
||||
$"accountBiometricIntegrityValid_{userId}_{systemBioIntegrityState}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user