mirror of
https://github.com/bitwarden/mobile.git
synced 2024-12-27 17:08:00 +01:00
clear cipher cache when replacing ios autofill identities (#1112)
* clear cipher cache when replacing ios autofill identities * changed to be service-centric * support for multiple cache keys * async suffix * added cache keys for android
This commit is contained in:
parent
37e19d9a60
commit
0b7e07ebab
@ -41,7 +41,8 @@ namespace Bit.Droid
|
|||||||
{
|
{
|
||||||
RegisterLocalServices();
|
RegisterLocalServices();
|
||||||
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
ServiceContainer.Init(deviceActionService.DeviceUserAgent);
|
ServiceContainer.Init(deviceActionService.DeviceUserAgent, Constants.ClearCiphersCacheKey,
|
||||||
|
Constants.AndroidAllClearCipherCacheKeys);
|
||||||
}
|
}
|
||||||
#if !FDROID
|
#if !FDROID
|
||||||
if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)
|
if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)
|
||||||
|
@ -163,7 +163,6 @@ namespace Bit.App
|
|||||||
{
|
{
|
||||||
System.Diagnostics.Debug.WriteLine("XF App: OnStart");
|
System.Diagnostics.Debug.WriteLine("XF App: OnStart");
|
||||||
await ClearCacheIfNeededAsync();
|
await ClearCacheIfNeededAsync();
|
||||||
await TryClearCiphersCacheAsync();
|
|
||||||
Prime();
|
Prime();
|
||||||
if (string.IsNullOrWhiteSpace(Options.Uri))
|
if (string.IsNullOrWhiteSpace(Options.Uri))
|
||||||
{
|
{
|
||||||
@ -214,7 +213,6 @@ namespace Bit.App
|
|||||||
_messagingService.Send("cancelVaultTimeoutTimer");
|
_messagingService.Send("cancelVaultTimeoutTimer");
|
||||||
_messagingService.Send("startEventTimer");
|
_messagingService.Send("startEventTimer");
|
||||||
await ClearCacheIfNeededAsync();
|
await ClearCacheIfNeededAsync();
|
||||||
await TryClearCiphersCacheAsync();
|
|
||||||
Prime();
|
Prime();
|
||||||
SyncIfNeeded();
|
SyncIfNeeded();
|
||||||
if (Current.MainPage is NavigationPage navPage && navPage.CurrentPage is LockPage lockPage)
|
if (Current.MainPage is NavigationPage navPage && navPage.CurrentPage is LockPage lockPage)
|
||||||
@ -390,20 +388,6 @@ namespace Bit.App
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TryClearCiphersCacheAsync()
|
|
||||||
{
|
|
||||||
if (Device.RuntimePlatform != Device.iOS)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var clearCache = await _storageService.GetAsync<bool?>(Constants.ClearCiphersCacheKey);
|
|
||||||
if (clearCache.GetValueOrDefault())
|
|
||||||
{
|
|
||||||
_cipherService.ClearCache();
|
|
||||||
await _storageService.RemoveAsync(Constants.ClearCiphersCacheKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LockedAsync(bool autoPromptBiometric)
|
private async Task LockedAsync(bool autoPromptBiometric)
|
||||||
{
|
{
|
||||||
await _stateService.PurgeAsync();
|
await _stateService.PurgeAsync();
|
||||||
|
@ -32,6 +32,8 @@ namespace Bit.App.Services
|
|||||||
Constants.MigratedFromV1AutofillPromptShown,
|
Constants.MigratedFromV1AutofillPromptShown,
|
||||||
Constants.TriedV1Resync,
|
Constants.TriedV1Resync,
|
||||||
Constants.ClearCiphersCacheKey,
|
Constants.ClearCiphersCacheKey,
|
||||||
|
Constants.iOSAutoFillClearCiphersCacheKey,
|
||||||
|
Constants.iOSExtensionClearCiphersCacheKey,
|
||||||
Constants.EnvironmentUrlsKey,
|
Constants.EnvironmentUrlsKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ namespace Bit.Core.Abstractions
|
|||||||
public interface ICipherService
|
public interface ICipherService
|
||||||
{
|
{
|
||||||
Task ClearAsync(string userId);
|
Task ClearAsync(string userId);
|
||||||
void ClearCache();
|
Task ClearCacheAsync();
|
||||||
Task DeleteAsync(List<string> ids);
|
Task DeleteAsync(List<string> ids);
|
||||||
Task DeleteAsync(string id);
|
Task DeleteAsync(string id);
|
||||||
Task DeleteAttachmentAsync(string id, string attachmentId);
|
Task DeleteAttachmentAsync(string id, string attachmentId);
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
public static string OldUserIdKey = "userId";
|
public static string OldUserIdKey = "userId";
|
||||||
public static string AddSitePromptShownKey = "addSitePromptShown";
|
public static string AddSitePromptShownKey = "addSitePromptShown";
|
||||||
public static string ClearCiphersCacheKey = "clearCiphersCache";
|
public static string ClearCiphersCacheKey = "clearCiphersCache";
|
||||||
|
public static string iOSAutoFillClearCiphersCacheKey = "iOSAutoFillClearCiphersCache";
|
||||||
|
public static string iOSExtensionClearCiphersCacheKey = "iOSExtensionClearCiphersCache";
|
||||||
public static string MigratedFromV1 = "migratedFromV1";
|
public static string MigratedFromV1 = "migratedFromV1";
|
||||||
public static string MigratedFromV1AutofillPromptShown = "migratedV1AutofillPromptShown";
|
public static string MigratedFromV1AutofillPromptShown = "migratedV1AutofillPromptShown";
|
||||||
public static string TriedV1Resync = "triedV1Resync";
|
public static string TriedV1Resync = "triedV1Resync";
|
||||||
@ -37,5 +39,17 @@
|
|||||||
public const int SelectFileRequestCode = 42;
|
public const int SelectFileRequestCode = 42;
|
||||||
public const int SelectFilePermissionRequestCode = 43;
|
public const int SelectFilePermissionRequestCode = 43;
|
||||||
public const int SaveFileRequestCode = 44;
|
public const int SaveFileRequestCode = 44;
|
||||||
|
|
||||||
|
public static readonly string[] AndroidAllClearCipherCacheKeys =
|
||||||
|
{
|
||||||
|
ClearCiphersCacheKey
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly string[] iOSAllClearCipherCacheKeys =
|
||||||
|
{
|
||||||
|
ClearCiphersCacheKey,
|
||||||
|
iOSAutoFillClearCiphersCacheKey,
|
||||||
|
iOSExtensionClearCiphersCacheKey
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@ namespace Bit.Core.Services
|
|||||||
private readonly IStorageService _storageService;
|
private readonly IStorageService _storageService;
|
||||||
private readonly II18nService _i18nService;
|
private readonly II18nService _i18nService;
|
||||||
private readonly Func<ISearchService> _searchService;
|
private readonly Func<ISearchService> _searchService;
|
||||||
|
private readonly string _clearCipherCacheKey;
|
||||||
|
private readonly string[] _allClearCipherCacheKeys;
|
||||||
private Dictionary<string, HashSet<string>> _domainMatchBlacklist = new Dictionary<string, HashSet<string>>
|
private Dictionary<string, HashSet<string>> _domainMatchBlacklist = new Dictionary<string, HashSet<string>>
|
||||||
{
|
{
|
||||||
["google.com"] = new HashSet<string> { "script.google.com" }
|
["google.com"] = new HashSet<string> { "script.google.com" }
|
||||||
@ -47,7 +49,9 @@ namespace Bit.Core.Services
|
|||||||
IApiService apiService,
|
IApiService apiService,
|
||||||
IStorageService storageService,
|
IStorageService storageService,
|
||||||
II18nService i18nService,
|
II18nService i18nService,
|
||||||
Func<ISearchService> searchService)
|
Func<ISearchService> searchService,
|
||||||
|
string clearCipherCacheKey,
|
||||||
|
string[] allClearCipherCacheKeys)
|
||||||
{
|
{
|
||||||
_cryptoService = cryptoService;
|
_cryptoService = cryptoService;
|
||||||
_userService = userService;
|
_userService = userService;
|
||||||
@ -56,6 +60,8 @@ namespace Bit.Core.Services
|
|||||||
_storageService = storageService;
|
_storageService = storageService;
|
||||||
_i18nService = i18nService;
|
_i18nService = i18nService;
|
||||||
_searchService = searchService;
|
_searchService = searchService;
|
||||||
|
_clearCipherCacheKey = clearCipherCacheKey;
|
||||||
|
_allClearCipherCacheKeys = allClearCipherCacheKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<CipherView> DecryptedCipherCache
|
private List<CipherView> DecryptedCipherCache
|
||||||
@ -82,9 +88,16 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearCache()
|
public async Task ClearCacheAsync()
|
||||||
{
|
{
|
||||||
DecryptedCipherCache = null;
|
DecryptedCipherCache = null;
|
||||||
|
if (_allClearCipherCacheKeys != null && _allClearCipherCacheKeys.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var key in _allClearCipherCacheKeys)
|
||||||
|
{
|
||||||
|
await _storageService.SaveAsync(key, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Cipher> EncryptAsync(CipherView model, SymmetricCryptoKey key = null,
|
public async Task<Cipher> EncryptAsync(CipherView model, SymmetricCryptoKey key = null,
|
||||||
@ -218,15 +231,24 @@ namespace Bit.Core.Services
|
|||||||
return response?.ToList() ?? new List<Cipher>();
|
return response?.ToList() ?? new List<Cipher>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<CipherView>> GetAllDecryptedAsync()
|
public async Task<List<CipherView>> GetAllDecryptedAsync()
|
||||||
{
|
{
|
||||||
|
if (_clearCipherCacheKey != null)
|
||||||
|
{
|
||||||
|
var clearCache = await _storageService.GetAsync<bool?>(_clearCipherCacheKey);
|
||||||
|
if (clearCache.GetValueOrDefault())
|
||||||
|
{
|
||||||
|
DecryptedCipherCache = null;
|
||||||
|
await _storageService.RemoveAsync(_clearCipherCacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (DecryptedCipherCache != null)
|
if (DecryptedCipherCache != null)
|
||||||
{
|
{
|
||||||
return Task.FromResult(DecryptedCipherCache);
|
return DecryptedCipherCache;
|
||||||
}
|
}
|
||||||
if (_getAllDecryptedTask != null && !_getAllDecryptedTask.IsCompleted && !_getAllDecryptedTask.IsFaulted)
|
if (_getAllDecryptedTask != null && !_getAllDecryptedTask.IsCompleted && !_getAllDecryptedTask.IsFaulted)
|
||||||
{
|
{
|
||||||
return _getAllDecryptedTask;
|
return await _getAllDecryptedTask;
|
||||||
}
|
}
|
||||||
async Task<List<CipherView>> doTask()
|
async Task<List<CipherView>> doTask()
|
||||||
{
|
{
|
||||||
@ -257,7 +279,7 @@ namespace Bit.Core.Services
|
|||||||
finally { }
|
finally { }
|
||||||
}
|
}
|
||||||
_getAllDecryptedTask = doTask();
|
_getAllDecryptedTask = doTask();
|
||||||
return _getAllDecryptedTask;
|
return await _getAllDecryptedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<CipherView>> GetAllDecryptedForGroupingAsync(string groupingId, bool folder = true)
|
public async Task<List<CipherView>> GetAllDecryptedForGroupingAsync(string groupingId, bool folder = true)
|
||||||
@ -569,7 +591,7 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
ciphers[cipher.Id] = cipher;
|
ciphers[cipher.Id] = cipher;
|
||||||
await _storageService.SaveAsync(storageKey, ciphers);
|
await _storageService.SaveAsync(storageKey, ciphers);
|
||||||
DecryptedCipherCache = null;
|
await ClearCacheAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpsertAsync(List<CipherData> cipher)
|
public async Task UpsertAsync(List<CipherData> cipher)
|
||||||
@ -590,20 +612,20 @@ namespace Bit.Core.Services
|
|||||||
ciphers[c.Id] = c;
|
ciphers[c.Id] = c;
|
||||||
}
|
}
|
||||||
await _storageService.SaveAsync(storageKey, ciphers);
|
await _storageService.SaveAsync(storageKey, ciphers);
|
||||||
DecryptedCipherCache = null;
|
await ClearCacheAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ReplaceAsync(Dictionary<string, CipherData> ciphers)
|
public async Task ReplaceAsync(Dictionary<string, CipherData> ciphers)
|
||||||
{
|
{
|
||||||
var userId = await _userService.GetUserIdAsync();
|
var userId = await _userService.GetUserIdAsync();
|
||||||
await _storageService.SaveAsync(string.Format(Keys_CiphersFormat, userId), ciphers);
|
await _storageService.SaveAsync(string.Format(Keys_CiphersFormat, userId), ciphers);
|
||||||
DecryptedCipherCache = null;
|
await ClearCacheAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ClearAsync(string userId)
|
public async Task ClearAsync(string userId)
|
||||||
{
|
{
|
||||||
await _storageService.RemoveAsync(string.Format(Keys_CiphersFormat, userId));
|
await _storageService.RemoveAsync(string.Format(Keys_CiphersFormat, userId));
|
||||||
ClearCache();
|
await ClearCacheAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteAsync(string id)
|
public async Task DeleteAsync(string id)
|
||||||
@ -621,7 +643,7 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
ciphers.Remove(id);
|
ciphers.Remove(id);
|
||||||
await _storageService.SaveAsync(cipherKey, ciphers);
|
await _storageService.SaveAsync(cipherKey, ciphers);
|
||||||
DecryptedCipherCache = null;
|
await ClearCacheAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteAsync(List<string> ids)
|
public async Task DeleteAsync(List<string> ids)
|
||||||
@ -642,7 +664,7 @@ namespace Bit.Core.Services
|
|||||||
ciphers.Remove(id);
|
ciphers.Remove(id);
|
||||||
}
|
}
|
||||||
await _storageService.SaveAsync(cipherKey, ciphers);
|
await _storageService.SaveAsync(cipherKey, ciphers);
|
||||||
DecryptedCipherCache = null;
|
await ClearCacheAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteWithServerAsync(string id)
|
public async Task DeleteWithServerAsync(string id)
|
||||||
@ -666,7 +688,7 @@ namespace Bit.Core.Services
|
|||||||
ciphers[id].Attachments.Remove(attachment);
|
ciphers[id].Attachments.Remove(attachment);
|
||||||
}
|
}
|
||||||
await _storageService.SaveAsync(cipherKey, ciphers);
|
await _storageService.SaveAsync(cipherKey, ciphers);
|
||||||
DecryptedCipherCache = null;
|
await ClearCacheAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteAttachmentWithServerAsync(string id, string attachmentId)
|
public async Task DeleteAttachmentWithServerAsync(string id, string attachmentId)
|
||||||
@ -721,7 +743,7 @@ namespace Bit.Core.Services
|
|||||||
await _apiService.PutDeleteCipherAsync(id);
|
await _apiService.PutDeleteCipherAsync(id);
|
||||||
ciphers[id].DeletedDate = DateTime.UtcNow;
|
ciphers[id].DeletedDate = DateTime.UtcNow;
|
||||||
await _storageService.SaveAsync(cipherKey, ciphers);
|
await _storageService.SaveAsync(cipherKey, ciphers);
|
||||||
DecryptedCipherCache = null;
|
await ClearCacheAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RestoreWithServerAsync(string id)
|
public async Task RestoreWithServerAsync(string id)
|
||||||
@ -740,7 +762,7 @@ namespace Bit.Core.Services
|
|||||||
await _apiService.PutRestoreCipherAsync(id);
|
await _apiService.PutRestoreCipherAsync(id);
|
||||||
ciphers[id].DeletedDate = null;
|
ciphers[id].DeletedDate = null;
|
||||||
await _storageService.SaveAsync(cipherKey, ciphers);
|
await _storageService.SaveAsync(cipherKey, ciphers);
|
||||||
DecryptedCipherCache = null;
|
await ClearCacheAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
@ -135,7 +135,7 @@ namespace Bit.Core.Services
|
|||||||
_cryptoService.ClearEncKeyAsync(true));
|
_cryptoService.ClearEncKeyAsync(true));
|
||||||
|
|
||||||
_folderService.ClearCache();
|
_folderService.ClearCache();
|
||||||
_cipherService.ClearCache();
|
await _cipherService.ClearCacheAsync();
|
||||||
_collectionService.ClearCache();
|
_collectionService.ClearCache();
|
||||||
_searchService.ClearIndex();
|
_searchService.ClearIndex();
|
||||||
_messagingService.Send("locked", userInitiated);
|
_messagingService.Send("locked", userInitiated);
|
||||||
|
@ -11,7 +11,8 @@ namespace Bit.Core.Utilities
|
|||||||
public static Dictionary<string, object> RegisteredServices { get; set; } = new Dictionary<string, object>();
|
public static Dictionary<string, object> RegisteredServices { get; set; } = new Dictionary<string, object>();
|
||||||
public static bool Inited { get; set; }
|
public static bool Inited { get; set; }
|
||||||
|
|
||||||
public static void Init(string customUserAgent = null)
|
public static void Init(string customUserAgent = null, string clearCipherCacheKey = null,
|
||||||
|
string[] allClearCipherCacheKeys = null)
|
||||||
{
|
{
|
||||||
if (Inited)
|
if (Inited)
|
||||||
{
|
{
|
||||||
@ -40,7 +41,7 @@ namespace Bit.Core.Utilities
|
|||||||
var userService = new UserService(storageService, tokenService);
|
var userService = new UserService(storageService, tokenService);
|
||||||
var settingsService = new SettingsService(userService, storageService);
|
var settingsService = new SettingsService(userService, storageService);
|
||||||
var cipherService = new CipherService(cryptoService, userService, settingsService, apiService,
|
var cipherService = new CipherService(cryptoService, userService, settingsService, apiService,
|
||||||
storageService, i18nService, () => searchService);
|
storageService, i18nService, () => searchService, clearCipherCacheKey, allClearCipherCacheKeys);
|
||||||
var folderService = new FolderService(cryptoService, userService, apiService, storageService,
|
var folderService = new FolderService(cryptoService, userService, apiService, storageService,
|
||||||
i18nService, cipherService);
|
i18nService, cipherService);
|
||||||
var collectionService = new CollectionService(cryptoService, userService, storageService, i18nService);
|
var collectionService = new CollectionService(cryptoService, userService, storageService, i18nService);
|
||||||
|
@ -273,7 +273,8 @@ namespace Bit.iOS.Autofill
|
|||||||
iOSCoreHelpers.RegisterLocalServices();
|
iOSCoreHelpers.RegisterLocalServices();
|
||||||
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
||||||
ServiceContainer.Init(deviceActionService.DeviceUserAgent);
|
ServiceContainer.Init(deviceActionService.DeviceUserAgent,
|
||||||
|
Bit.Core.Constants.iOSAutoFillClearCiphersCacheKey, Bit.Core.Constants.iOSAllClearCipherCacheKeys);
|
||||||
if (!_initedAppCenter)
|
if (!_initedAppCenter)
|
||||||
{
|
{
|
||||||
iOSCoreHelpers.RegisterAppCenter();
|
iOSCoreHelpers.RegisterAppCenter();
|
||||||
|
@ -395,7 +395,8 @@ namespace Bit.iOS.Extension
|
|||||||
iOSCoreHelpers.RegisterLocalServices();
|
iOSCoreHelpers.RegisterLocalServices();
|
||||||
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
||||||
ServiceContainer.Init(deviceActionService.DeviceUserAgent);
|
ServiceContainer.Init(deviceActionService.DeviceUserAgent,
|
||||||
|
Bit.Core.Constants.iOSExtensionClearCiphersCacheKey, Bit.Core.Constants.iOSAllClearCipherCacheKeys);
|
||||||
if (!_initedAppCenter)
|
if (!_initedAppCenter)
|
||||||
{
|
{
|
||||||
iOSCoreHelpers.RegisterAppCenter();
|
iOSCoreHelpers.RegisterAppCenter();
|
||||||
|
@ -301,7 +301,8 @@ namespace Bit.iOS
|
|||||||
iOSCoreHelpers.RegisterLocalServices();
|
iOSCoreHelpers.RegisterLocalServices();
|
||||||
RegisterPush();
|
RegisterPush();
|
||||||
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
ServiceContainer.Init(deviceActionService.DeviceUserAgent);
|
ServiceContainer.Init(deviceActionService.DeviceUserAgent, Constants.ClearCiphersCacheKey,
|
||||||
|
Constants.iOSAllClearCipherCacheKeys);
|
||||||
iOSCoreHelpers.RegisterAppCenter();
|
iOSCoreHelpers.RegisterAppCenter();
|
||||||
_pushHandler = new iOSPushNotificationHandler(
|
_pushHandler = new iOSPushNotificationHandler(
|
||||||
ServiceContainer.Resolve<IPushNotificationListenerService>("pushNotificationListenerService"));
|
ServiceContainer.Resolve<IPushNotificationListenerService>("pushNotificationListenerService"));
|
||||||
|
Loading…
Reference in New Issue
Block a user