From 5b5f563d476f60eef824c8219456283782926158 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Tue, 26 Aug 2025 10:02:19 +0530 Subject: [PATCH 1/4] Refactor BaseConfiguration to preserve offlineAuthSecretKey during logout --- .../configuration/lib/base_configuration.dart | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/mobile/packages/configuration/lib/base_configuration.dart b/mobile/packages/configuration/lib/base_configuration.dart index 5dfc722834..59b346c6f9 100644 --- a/mobile/packages/configuration/lib/base_configuration.dart +++ b/mobile/packages/configuration/lib/base_configuration.dart @@ -4,11 +4,11 @@ import 'dart:convert'; import 'dart:io' as io; import 'package:bip39/bip39.dart' as bip39; -import 'package:ente_configuration/constants.dart'; import 'package:ente_base/models/database.dart'; import 'package:ente_base/models/key_attributes.dart'; import 'package:ente_base/models/key_gen_result.dart'; import 'package:ente_base/models/private_key_attributes.dart'; +import 'package:ente_configuration/constants.dart'; import 'package:ente_crypto_dart/ente_crypto_dart.dart'; import 'package:ente_events/event_bus.dart'; import 'package:ente_events/models/endpoint_updated_event.dart'; @@ -35,11 +35,19 @@ class BaseConfiguration { static const userIDKey = "user_id"; static const endPointKey = "endpoint"; static const lastTempFolderClearTimeKey = "last_temp_folder_clear_time"; + static const offlineAuthSecretKey = "offline_auth_secret_key"; final kTempFolderDeletionTimeBuffer = const Duration(days: 1).inMicroseconds; static final _logger = Logger("Configuration"); + // Keys that should not be deleted during logout + // These keys are necessary for functionality that needs to work even when users + // aren't signed in. E.g offline auth + List preservedKeys = [ + offlineAuthSecretKey, + ]; + String? _cachedToken; late SharedPreferences _preferences; String? _key; @@ -62,13 +70,19 @@ class BaseConfiguration { accessibility: KeychainAccessibility.first_unlock_this_device, ), ); - _setupKeys(); - _setupFolders(); + await _setupKeys(); + await _setupFolders(); } Future logout({bool autoLogout = false}) async { await _preferences.clear(); - _secureStorage.deleteAll(); + // Delete all keys except preserved ones + final allKeys = await _secureStorage.readAll(); + for (final key in allKeys.keys) { + if (!preservedKeys.contains(key)) { + await _secureStorage.delete(key: key); + } + } for (final db in _databases) { await db.clearTable(); } @@ -217,7 +231,7 @@ class BaseConfiguration { if (split.length != mnemonicKeyWordCount) { String wordThatIsFollowedByEmptySpaceInSplit = ''; for (int i = 0; i < split.length; i++) { - String word = split[i]; + final String word = split[i]; if (word.isEmpty) { wordThatIsFollowedByEmptySpaceInSplit = '\n\nExtra space after word at position $i'; @@ -379,10 +393,17 @@ class BaseConfiguration { return _volatilePassword; } - Future _setupKeys() async { + Future _setupKeys() async { try { if (!_preferences.containsKey(tokenKey)) { - await _secureStorage.deleteAll(); + _logger.info("No token found, clearing secure storage"); + // Delete all keys except preserved ones + final allKeys = await _secureStorage.readAll(); + for (final key in allKeys.keys) { + if (!preservedKeys.contains(key)) { + await _secureStorage.delete(key: key); + } + } return; } _key = await _secureStorage.read(key: keyKey); From e49084867eb565ddc77dbd8f3cdb99601ee0f8c5 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Tue, 26 Aug 2025 12:21:00 +0530 Subject: [PATCH 2/4] Revert "Refactor BaseConfiguration to preserve offlineAuthSecretKey during logout" This reverts commit 5b5f563d476f60eef824c8219456283782926158. --- .../configuration/lib/base_configuration.dart | 35 ++++--------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/mobile/packages/configuration/lib/base_configuration.dart b/mobile/packages/configuration/lib/base_configuration.dart index 59b346c6f9..5dfc722834 100644 --- a/mobile/packages/configuration/lib/base_configuration.dart +++ b/mobile/packages/configuration/lib/base_configuration.dart @@ -4,11 +4,11 @@ import 'dart:convert'; import 'dart:io' as io; import 'package:bip39/bip39.dart' as bip39; +import 'package:ente_configuration/constants.dart'; import 'package:ente_base/models/database.dart'; import 'package:ente_base/models/key_attributes.dart'; import 'package:ente_base/models/key_gen_result.dart'; import 'package:ente_base/models/private_key_attributes.dart'; -import 'package:ente_configuration/constants.dart'; import 'package:ente_crypto_dart/ente_crypto_dart.dart'; import 'package:ente_events/event_bus.dart'; import 'package:ente_events/models/endpoint_updated_event.dart'; @@ -35,19 +35,11 @@ class BaseConfiguration { static const userIDKey = "user_id"; static const endPointKey = "endpoint"; static const lastTempFolderClearTimeKey = "last_temp_folder_clear_time"; - static const offlineAuthSecretKey = "offline_auth_secret_key"; final kTempFolderDeletionTimeBuffer = const Duration(days: 1).inMicroseconds; static final _logger = Logger("Configuration"); - // Keys that should not be deleted during logout - // These keys are necessary for functionality that needs to work even when users - // aren't signed in. E.g offline auth - List preservedKeys = [ - offlineAuthSecretKey, - ]; - String? _cachedToken; late SharedPreferences _preferences; String? _key; @@ -70,19 +62,13 @@ class BaseConfiguration { accessibility: KeychainAccessibility.first_unlock_this_device, ), ); - await _setupKeys(); - await _setupFolders(); + _setupKeys(); + _setupFolders(); } Future logout({bool autoLogout = false}) async { await _preferences.clear(); - // Delete all keys except preserved ones - final allKeys = await _secureStorage.readAll(); - for (final key in allKeys.keys) { - if (!preservedKeys.contains(key)) { - await _secureStorage.delete(key: key); - } - } + _secureStorage.deleteAll(); for (final db in _databases) { await db.clearTable(); } @@ -231,7 +217,7 @@ class BaseConfiguration { if (split.length != mnemonicKeyWordCount) { String wordThatIsFollowedByEmptySpaceInSplit = ''; for (int i = 0; i < split.length; i++) { - final String word = split[i]; + String word = split[i]; if (word.isEmpty) { wordThatIsFollowedByEmptySpaceInSplit = '\n\nExtra space after word at position $i'; @@ -393,17 +379,10 @@ class BaseConfiguration { return _volatilePassword; } - Future _setupKeys() async { + Future _setupKeys() async { try { if (!_preferences.containsKey(tokenKey)) { - _logger.info("No token found, clearing secure storage"); - // Delete all keys except preserved ones - final allKeys = await _secureStorage.readAll(); - for (final key in allKeys.keys) { - if (!preservedKeys.contains(key)) { - await _secureStorage.delete(key: key); - } - } + await _secureStorage.deleteAll(); return; } _key = await _secureStorage.read(key: keyKey); From fc32ba97c1962b5394912f8b4ce59018a31a9323 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Tue, 26 Aug 2025 12:26:01 +0530 Subject: [PATCH 3/4] Refactor BaseConfiguration to ensure preserved keys are not deleted --- .../configuration/lib/base_configuration.dart | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/mobile/packages/configuration/lib/base_configuration.dart b/mobile/packages/configuration/lib/base_configuration.dart index 5dfc722834..24224de339 100644 --- a/mobile/packages/configuration/lib/base_configuration.dart +++ b/mobile/packages/configuration/lib/base_configuration.dart @@ -4,11 +4,11 @@ import 'dart:convert'; import 'dart:io' as io; import 'package:bip39/bip39.dart' as bip39; -import 'package:ente_configuration/constants.dart'; import 'package:ente_base/models/database.dart'; import 'package:ente_base/models/key_attributes.dart'; import 'package:ente_base/models/key_gen_result.dart'; import 'package:ente_base/models/private_key_attributes.dart'; +import 'package:ente_configuration/constants.dart'; import 'package:ente_crypto_dart/ente_crypto_dart.dart'; import 'package:ente_events/event_bus.dart'; import 'package:ente_events/models/endpoint_updated_event.dart'; @@ -35,6 +35,7 @@ class BaseConfiguration { static const userIDKey = "user_id"; static const endPointKey = "endpoint"; static const lastTempFolderClearTimeKey = "last_temp_folder_clear_time"; + static const offlineAuthSecretKey = "offline_auth_secret_key"; final kTempFolderDeletionTimeBuffer = const Duration(days: 1).inMicroseconds; @@ -52,6 +53,11 @@ class BaseConfiguration { String? _volatilePassword; + // Keys that should not be deleted during logout + // These keys are necessary for functionality that needs to work even when users + // aren't signed in, such as using Auth without backup + List preservedKeys = [offlineAuthSecretKey]; + Future init(List dbs) async { _databases = dbs; _documentsDirectory = (await getApplicationDocumentsDirectory()).path; @@ -62,13 +68,20 @@ class BaseConfiguration { accessibility: KeychainAccessibility.first_unlock_this_device, ), ); - _setupKeys(); - _setupFolders(); + await _setupKeys(); + await _setupFolders(); } Future logout({bool autoLogout = false}) async { await _preferences.clear(); - _secureStorage.deleteAll(); + + // Delete all keys except preserved ones + final allKeys = await _secureStorage.readAll(); + for (final key in allKeys.keys) { + if (!preservedKeys.contains(key)) { + await _secureStorage.delete(key: key); + } + } for (final db in _databases) { await db.clearTable(); } @@ -217,7 +230,7 @@ class BaseConfiguration { if (split.length != mnemonicKeyWordCount) { String wordThatIsFollowedByEmptySpaceInSplit = ''; for (int i = 0; i < split.length; i++) { - String word = split[i]; + final String word = split[i]; if (word.isEmpty) { wordThatIsFollowedByEmptySpaceInSplit = '\n\nExtra space after word at position $i'; @@ -382,7 +395,15 @@ class BaseConfiguration { Future _setupKeys() async { try { if (!_preferences.containsKey(tokenKey)) { - await _secureStorage.deleteAll(); + + // Delete all keys except preserved ones + final allKeys = await _secureStorage.readAll(); + for (final key in allKeys.keys) { + if (!preservedKeys.contains(key)) { + await _secureStorage.delete(key: key); + } + } + return; } _key = await _secureStorage.read(key: keyKey); From 37928cd2c6e31c032ed3089985296a06f59eddcd Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Tue, 26 Aug 2025 12:40:03 +0530 Subject: [PATCH 4/4] Code refractoring --- .../configuration/lib/base_configuration.dart | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/mobile/packages/configuration/lib/base_configuration.dart b/mobile/packages/configuration/lib/base_configuration.dart index 24224de339..d934faea08 100644 --- a/mobile/packages/configuration/lib/base_configuration.dart +++ b/mobile/packages/configuration/lib/base_configuration.dart @@ -55,7 +55,7 @@ class BaseConfiguration { // Keys that should not be deleted during logout // These keys are necessary for functionality that needs to work even when users - // aren't signed in, such as using Auth without backup + // aren't signed in, such as using Auth without backup List preservedKeys = [offlineAuthSecretKey]; Future init(List dbs) async { @@ -74,14 +74,7 @@ class BaseConfiguration { Future logout({bool autoLogout = false}) async { await _preferences.clear(); - - // Delete all keys except preserved ones - final allKeys = await _secureStorage.readAll(); - for (final key in allKeys.keys) { - if (!preservedKeys.contains(key)) { - await _secureStorage.delete(key: key); - } - } + await resetSecureStorage(); for (final db in _databases) { await db.clearTable(); } @@ -91,6 +84,16 @@ class BaseConfiguration { Bus.instance.fire(SignedOutEvent()); } + Future resetSecureStorage() async { + // Delete all keys except preserved ones + final allKeys = await _secureStorage.readAll(); + for (final key in allKeys.keys) { + if (!preservedKeys.contains(key)) { + await _secureStorage.delete(key: key); + } + } + } + Future generateKey(String password) async { // Create a master key final masterKey = CryptoUtil.generateKey(); @@ -395,15 +398,7 @@ class BaseConfiguration { Future _setupKeys() async { try { if (!_preferences.containsKey(tokenKey)) { - - // Delete all keys except preserved ones - final allKeys = await _secureStorage.readAll(); - for (final key in allKeys.keys) { - if (!preservedKeys.contains(key)) { - await _secureStorage.delete(key: key); - } - } - + await resetSecureStorage(); return; } _key = await _secureStorage.read(key: keyKey);