Remove the in-memory deviceKey (#1270)

This commit is contained in:
David Perez 2024-04-15 10:36:50 -05:00 committed by Álison Fernandes
parent 20f7811b6a
commit 921240d173
5 changed files with 11 additions and 54 deletions

View file

@ -119,15 +119,8 @@ interface AuthDiskSource {
/**
* Stores the device key for the given [userId].
*
* When [inMemoryOnly] is `true`, the value will only be available via a call to [getDeviceKey]
* during the current app session.
*/
fun storeDeviceKey(
userId: String,
deviceKey: String?,
inMemoryOnly: Boolean = false,
)
fun storeDeviceKey(userId: String, deviceKey: String?)
/**
* Gets the stored [PendingAuthRequestJson] for the given [userId].

View file

@ -56,7 +56,6 @@ class AuthDiskSourceImpl(
),
AuthDiskSource {
private val inMemoryDeviceKeys = mutableMapOf<String, String?>()
private val inMemoryPinProtectedUserKeys = mutableMapOf<String, String?>()
private val mutableOrganizationsFlowMap =
mutableMapOf<String, MutableSharedFlow<List<SyncResponseJson.Profile.Organization>?>>()
@ -200,15 +199,12 @@ class AuthDiskSourceImpl(
override fun getDeviceKey(
userId: String,
): String? = inMemoryDeviceKeys[userId] ?: getEncryptedString(key = "${DEVICE_KEY_KEY}_$userId")
): String? = getEncryptedString(key = "${DEVICE_KEY_KEY}_$userId")
override fun storeDeviceKey(
userId: String,
deviceKey: String?,
inMemoryOnly: Boolean,
) {
inMemoryDeviceKeys[userId] = deviceKey
if (inMemoryOnly) return
putEncryptedString(key = "${DEVICE_KEY_KEY}_$userId", value = deviceKey)
}

View file

@ -4,6 +4,7 @@ import com.bitwarden.crypto.TrustDeviceResponse
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
import com.x8bit.bitwarden.data.auth.datasource.network.service.DevicesService
import com.x8bit.bitwarden.data.auth.manager.util.toUserStateJson
import com.x8bit.bitwarden.data.platform.util.asSuccess
import com.x8bit.bitwarden.data.platform.util.flatMap
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
@ -17,19 +18,7 @@ class TrustedDeviceManagerImpl(
) : TrustedDeviceManager {
override suspend fun trustThisDeviceIfNecessary(userId: String): Result<Boolean> =
if (!authDiskSource.shouldTrustDevice) {
// Even though we are not trusting the device, we still store the device key in
// memory. This allows the user to be "trusted" for this session but on timeout
// or reboot, the "trust" will be gone.
vaultSdkSource
.getTrustDevice(userId = userId)
.onSuccess { trustedDevice ->
authDiskSource.storeDeviceKey(
userId = userId,
deviceKey = trustedDevice.deviceKey,
inMemoryOnly = true,
)
}
.map { false }
false.asSuccess()
} else {
vaultSdkSource
.getTrustDevice(userId = userId)

View file

@ -38,7 +38,7 @@ class FakeAuthDiskSource : AuthDiskSource {
mutableMapOf<String, List<SyncResponseJson.Profile.Organization>?>()
private val storedOrganizationKeys = mutableMapOf<String, Map<String, String>?>()
private val storedAccountTokens = mutableMapOf<String, AccountTokensJson?>()
private val storedDeviceKey = mutableMapOf<String, Pair<String?, Boolean>>()
private val storedDeviceKey = mutableMapOf<String, String?>()
private val storedPendingAuthRequests = mutableMapOf<String, PendingAuthRequestJson?>()
private val storedBiometricKeys = mutableMapOf<String, String?>()
private val storedMasterPasswordHashes = mutableMapOf<String, String?>()
@ -166,14 +166,10 @@ class FakeAuthDiskSource : AuthDiskSource {
getMutableOrganizationsFlow(userId = userId).tryEmit(organizations)
}
override fun getDeviceKey(userId: String): String? = storedDeviceKey[userId]?.first
override fun getDeviceKey(userId: String): String? = storedDeviceKey[userId]
override fun storeDeviceKey(
userId: String,
deviceKey: String?,
inMemoryOnly: Boolean,
) {
storedDeviceKey[userId] = deviceKey to inMemoryOnly
override fun storeDeviceKey(userId: String, deviceKey: String?) {
storedDeviceKey[userId] = deviceKey
}
override fun getPendingAuthRequest(userId: String): PendingAuthRequestJson? =
@ -301,8 +297,8 @@ class FakeAuthDiskSource : AuthDiskSource {
/**
* Assert that the [deviceKey] was stored successfully using the [userId].
*/
fun assertDeviceKey(userId: String, deviceKey: String?, inMemoryOnly: Boolean = false) {
assertEquals(deviceKey to inMemoryOnly, storedDeviceKey[userId])
fun assertDeviceKey(userId: String, deviceKey: String?) {
assertEquals(deviceKey, storedDeviceKey[userId])
}
/**

View file

@ -53,30 +53,13 @@ class TrustedDeviceManagerTests {
@Test
fun `trustThisDeviceIfNecessary when shouldTrustDevice false should return success with false`() =
runTest {
val deviceKey = "deviceKey"
val trustedDeviceResponse = TrustDeviceResponse(
deviceKey = deviceKey,
protectedUserKey = "protectedUserKey",
protectedDevicePrivateKey = "protectedDevicePrivateKey",
protectedDevicePublicKey = "protectedDevicePublicKey",
)
fakeAuthDiskSource.shouldTrustDevice = false
coEvery {
vaultSdkSource.getTrustDevice(userId = USER_ID)
} returns trustedDeviceResponse.asSuccess()
val result = manager.trustThisDeviceIfNecessary(userId = USER_ID)
assertEquals(false.asSuccess(), result)
fakeAuthDiskSource.assertDeviceKey(
userId = USER_ID,
deviceKey = deviceKey,
inMemoryOnly = true,
)
coVerify(exactly = 1) {
vaultSdkSource.getTrustDevice(userId = USER_ID)
}
coVerify(exactly = 0) {
vaultSdkSource.getTrustDevice(userId = USER_ID)
devicesService.trustDevice(
appId = any(),
encryptedUserKey = any(),