Skip to content

Commit 5f1304b

Browse files
authored
Merge pull request #2848 from wmathurin/dev
@W-17366971: Clear encryption keys and user info SharedPreferences on logout
2 parents 2d527da + afd5139 commit 5f1304b

4 files changed

Lines changed: 64 additions & 0 deletions

File tree

libs/SalesforceSDK/src/com/salesforce/androidsdk/accounts/UserAccountManager.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,4 +767,16 @@ private Bundle buildAuthBundle(UserAccount userAccount) {
767767
private String decryptUserData(Account account, String key, String encryptionKey) {
768768
return SalesforceSDKManager.decrypt(accountManager.getUserData(account, key), encryptionKey);
769769
}
770+
771+
/**
772+
* Clears the stored current user info from shared preferences. This should be called
773+
* when the last user logs out to ensure no user information remains on the device.
774+
*/
775+
public void clearStoredCurrentUserInfo() {
776+
clearCachedCurrentUser();
777+
final SharedPreferences sp = context.getSharedPreferences(CURRENT_USER_PREF,
778+
Context.MODE_PRIVATE);
779+
sp.edit().clear().apply();
780+
SalesforceSDKLogger.d(TAG, "Cleared current user info from shared preferences");
781+
}
770782
}

libs/SalesforceSDK/src/com/salesforce/androidsdk/app/SalesforceSDKManager.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ import com.salesforce.androidsdk.rest.NotificationsActionsResponseBody
128128
import com.salesforce.androidsdk.rest.NotificationsApiClient
129129
import com.salesforce.androidsdk.rest.RestClient
130130
import com.salesforce.androidsdk.security.BiometricAuthenticationManager
131+
import com.salesforce.androidsdk.security.SalesforceKeyGenerator
131132
import com.salesforce.androidsdk.security.SalesforceKeyGenerator.getEncryptionKey
132133
import com.salesforce.androidsdk.security.ScreenLockManager
133134
import com.salesforce.androidsdk.ui.AccountSwitcherActivity
@@ -790,6 +791,10 @@ open class SalesforceSDKManager protected constructor(
790791
(screenLockManager as ScreenLockManager?)?.reset()
791792
screenLockManager = null
792793
biometricAuthenticationManager = null
794+
795+
// Clear stored identifiers and user info from shared preferences
796+
SalesforceKeyGenerator.clearAll()
797+
userAccountManager.clearStoredCurrentUserInfo()
793798
}
794799
}
795800

libs/SalesforceSDK/src/com/salesforce/androidsdk/security/SalesforceKeyGenerator.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,15 @@ private static String getSharedPrefKey(String name) {
224224
final String suffix = TextUtils.isEmpty(name) ? "" : name;
225225
return String.format(Locale.US, ENCRYPTED_ID_SHARED_PREF_KEY, suffix);
226226
}
227+
228+
/**
229+
* Clears all stored identifiers from shared preferences. This should be called
230+
* when the last user logs out to ensure no encrypted identifiers remain on the device.
231+
*/
232+
public synchronized static void clearAll() {
233+
final SharedPreferences prefs = SalesforceSDKManager.getInstance().getAppContext().getSharedPreferences(SHARED_PREF_FILE, 0);
234+
prefs.edit().clear().apply();
235+
CACHED_ENCRYPTION_KEYS.clear();
236+
SalesforceSDKLogger.d(TAG, "Cleared all identifiers from shared preferences");
237+
}
227238
}

libs/test/SalesforceSDKTest/src/com/salesforce/androidsdk/accounts/UserAccountManagerTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import android.accounts.AccountManager;
3535
import android.content.Context;
3636
import android.content.IntentFilter;
37+
import android.content.SharedPreferences;
3738

3839
import androidx.core.content.ContextCompat;
3940
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -42,6 +43,7 @@
4243

4344
import com.salesforce.androidsdk.app.SalesforceSDKManager;
4445
import com.salesforce.androidsdk.auth.OAuth2;
46+
import com.salesforce.androidsdk.security.SalesforceKeyGenerator;
4547
import com.salesforce.androidsdk.util.LogoutCompleteReceiver;
4648

4749
import org.jetbrains.annotations.NotNull;
@@ -201,6 +203,40 @@ public void testSignoutBackgroundUser() {
201203
Assert.assertEquals(TEST_USERNAME, logoutCompleteReceiver.getLastUserAccountReceived().getUsername());
202204
}
203205

206+
/**
207+
* Test that shared preferences are cleared when the last user logs out.
208+
* This verifies the fix for W-17366971 - ensuring that identifier.xml
209+
* and current_user_info files are deleted on logout.
210+
*/
211+
@Test
212+
public void testSharedPreferencesCleanupOnLastUserLogout() {
213+
final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
214+
215+
// Create a user and force creation of identifier.xml by accessing the encryption key
216+
createTestAccountInAccountManager(userAccMgr);
217+
String encryptionKey = SalesforceKeyGenerator.getEncryptionKey("test_key");
218+
Assert.assertNotNull("Encryption key should be created", encryptionKey);
219+
220+
// Verify that identifier.xml shared preferences exists with data
221+
SharedPreferences identifierPrefs = context.getSharedPreferences("identifier.xml", 0);
222+
Assert.assertFalse("identifier.xml should have data", identifierPrefs.getAll().isEmpty());
223+
224+
// Verify that current_user_info shared preferences exists with data
225+
SharedPreferences currentUserPrefs = context.getSharedPreferences("current_user_info", 0);
226+
Assert.assertFalse("current_user_info should have data", currentUserPrefs.getAll().isEmpty());
227+
228+
// Logout the last user
229+
userAccMgr.signoutCurrentUser(null, false, OAuth2.LogoutReason.USER_LOGOUT);
230+
231+
// Verify that identifier.xml shared preferences is cleared
232+
identifierPrefs = context.getSharedPreferences("identifier.xml", 0);
233+
Assert.assertTrue("identifier.xml should be empty after logout", identifierPrefs.getAll().isEmpty());
234+
235+
// Verify that current_user_info shared preferences is cleared
236+
currentUserPrefs = context.getSharedPreferences("current_user_info", 0);
237+
Assert.assertTrue("current_user_info should be empty after logout", currentUserPrefs.getAll().isEmpty());
238+
}
239+
204240
/**
205241
* Removes any existing accounts.
206242
*/

0 commit comments

Comments
 (0)