diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepository.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepository.kt index e898fc33f..2607a613b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepository.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepository.kt @@ -10,7 +10,7 @@ interface AuthenticatorBridgeRepository { /** * The currently persisted authenticator sync symmetric key. This key is used for - * encrypting IPC traffic. + * encrypting IPC traffic. This will return null if no users have enabled authenticator sync. */ val authenticatorSyncSymmetricKey: ByteArray? diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepositoryImpl.kt index 35de7ad9d..d906fe57f 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepositoryImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepositoryImpl.kt @@ -26,7 +26,23 @@ class AuthenticatorBridgeRepositoryImpl( ) : AuthenticatorBridgeRepository { override val authenticatorSyncSymmetricKey: ByteArray? - get() = authDiskSource.authenticatorSyncSymmetricKey + get() { + val doAnyAccountsHaveAuthenticatorSyncEnabled = authRepository + .userStateFlow + .value + ?.accounts + ?.any { + // Authenticator sync is enabled if any accounts have an authenticator + // sync key stored: + authDiskSource.getAuthenticatorSyncUnlockKey(it.userId) != null + } + ?: false + return if (doAnyAccountsHaveAuthenticatorSyncEnabled) { + authDiskSource.authenticatorSyncSymmetricKey + } else { + null + } + } @Suppress("LongMethod") override suspend fun getSharedAccounts(): SharedAccountData { diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepositoryTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepositoryTest.kt index 1d45f2113..f76b28ed5 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepositoryTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/AuthenticatorBridgeRepositoryTest.kt @@ -334,7 +334,14 @@ class AuthenticatorBridgeRepositoryTest { } @Test - fun `authenticatorSyncSymmetricKey should read from authDiskSource`() { + @Suppress("MaxLineLength") + fun `authenticatorSyncSymmetricKey should read from authDiskSource when one user has authenticator sync enabled`() { + every { authRepository.userStateFlow } returns MutableStateFlow(USER_STATE) + fakeAuthDiskSource.storeAuthenticatorSyncUnlockKey( + userId = USER_1_ID, + authenticatorSyncUnlockKey = USER_1_UNLOCK_KEY, + ) + fakeAuthDiskSource.authenticatorSyncSymmetricKey = null assertNull(authenticatorBridgeRepository.authenticatorSyncSymmetricKey) @@ -342,6 +349,29 @@ class AuthenticatorBridgeRepositoryTest { fakeAuthDiskSource.authenticatorSyncSymmetricKey = syncKey assertEquals(syncKey, authenticatorBridgeRepository.authenticatorSyncSymmetricKey) + verify { authRepository.userStateFlow } + } + + @Test + @Suppress("MaxLineLength") + fun `authenticatorSyncSymmetricKey should return null when no user has authenticator sync enabled`() { + every { authRepository.userStateFlow } returns MutableStateFlow(USER_STATE) + fakeAuthDiskSource.storeAuthenticatorSyncUnlockKey( + userId = USER_1_ID, + authenticatorSyncUnlockKey = null, + ) + fakeAuthDiskSource.storeAuthenticatorSyncUnlockKey( + userId = USER_2_ID, + authenticatorSyncUnlockKey = null, + ) + + fakeAuthDiskSource.authenticatorSyncSymmetricKey = null + assertNull(authenticatorBridgeRepository.authenticatorSyncSymmetricKey) + + val syncKey = generateSecretKey().getOrThrow().encoded + fakeAuthDiskSource.authenticatorSyncSymmetricKey = syncKey + assertNull(authenticatorBridgeRepository.authenticatorSyncSymmetricKey) + verify { authRepository.userStateFlow } } }