mirror of
https://github.com/bitwarden/android.git
synced 2025-03-15 10:48:47 +03:00
Add auto unlock key storage (#544)
This commit is contained in:
parent
6686d98e34
commit
940979599e
4 changed files with 77 additions and 0 deletions
|
@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.Flow
|
|||
/**
|
||||
* Primary access point for disk information.
|
||||
*/
|
||||
@Suppress("TooManyFunctions")
|
||||
interface AuthDiskSource {
|
||||
/**
|
||||
* Retrieves a unique ID for the application that is stored locally. This will generate a new
|
||||
|
@ -50,6 +51,16 @@ interface AuthDiskSource {
|
|||
*/
|
||||
fun storePrivateKey(userId: String, privateKey: String?)
|
||||
|
||||
/**
|
||||
* Retrieves a user auto-unlock key for the given [userId].
|
||||
*/
|
||||
fun getUserAutoUnlockKey(userId: String): String?
|
||||
|
||||
/**
|
||||
* Stores a user auto-unlock key for the given [userId].
|
||||
*/
|
||||
fun storeUserAutoUnlockKey(userId: String, userAutoUnlockKey: String?)
|
||||
|
||||
/**
|
||||
* Gets the organization keys for the given [userId] in the form of a mapping from organization
|
||||
* ID to encrypted organization key.
|
||||
|
|
|
@ -4,6 +4,8 @@ import android.content.SharedPreferences
|
|||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
||||
import com.x8bit.bitwarden.data.platform.datasource.disk.BaseDiskSource.Companion.BASE_KEY
|
||||
import com.x8bit.bitwarden.data.platform.datasource.disk.BaseEncryptedDiskSource
|
||||
|
||||
import com.x8bit.bitwarden.data.platform.datasource.disk.BaseEncryptedDiskSource.Companion.ENCRYPTED_BASE_KEY
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -13,6 +15,7 @@ import kotlinx.serialization.encodeToString
|
|||
import kotlinx.serialization.json.Json
|
||||
import java.util.UUID
|
||||
|
||||
private const val USER_AUTO_UNLOCK_KEY_KEY = "$ENCRYPTED_BASE_KEY:userKeyAutoUnlock"
|
||||
private const val UNIQUE_APP_ID_KEY = "$BASE_KEY:appId"
|
||||
private const val REMEMBERED_EMAIL_ADDRESS_KEY = "$BASE_KEY:rememberedEmail"
|
||||
private const val STATE_KEY = "$BASE_KEY:state"
|
||||
|
@ -85,6 +88,22 @@ class AuthDiskSourceImpl(
|
|||
)
|
||||
}
|
||||
|
||||
override fun getUserAutoUnlockKey(userId: String): String? =
|
||||
getEncryptedString(
|
||||
key = "${USER_AUTO_UNLOCK_KEY_KEY}_$userId",
|
||||
default = null,
|
||||
)
|
||||
|
||||
override fun storeUserAutoUnlockKey(
|
||||
userId: String,
|
||||
userAutoUnlockKey: String?,
|
||||
) {
|
||||
putEncryptedString(
|
||||
key = "${USER_AUTO_UNLOCK_KEY_KEY}_$userId",
|
||||
value = userAutoUnlockKey,
|
||||
)
|
||||
}
|
||||
|
||||
override fun getOrganizationKeys(userId: String): Map<String, String>? =
|
||||
getString(key = "${ORGANIZATION_KEYS_KEY}_$userId")
|
||||
?.let { json.decodeFromString(it) }
|
||||
|
|
|
@ -193,6 +193,45 @@ class AuthDiskSourceTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getUserAutoUnlockKey should pull from SharedPreferences`() {
|
||||
val userAutoUnlockKeyBaseKey = "bwSecureStorage:userKeyAutoUnlock"
|
||||
val mockUserId = "mockUserId"
|
||||
val mockUserAutoUnlockKey = "mockUserAutoUnlockKey"
|
||||
fakeEncryptedSharedPreferences
|
||||
.edit()
|
||||
.putString(
|
||||
"${userAutoUnlockKeyBaseKey}_$mockUserId",
|
||||
mockUserAutoUnlockKey,
|
||||
)
|
||||
.apply()
|
||||
val actual = authDiskSource.getUserAutoUnlockKey(userId = mockUserId)
|
||||
assertEquals(
|
||||
mockUserAutoUnlockKey,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `storeUserAutoUnlockKey should update SharedPreferences`() {
|
||||
val userAutoUnlockKeyBaseKey = "bwSecureStorage:userKeyAutoUnlock"
|
||||
val mockUserId = "mockUserId"
|
||||
val mockUserAutoUnlockKey = "mockUserAutoUnlockKey"
|
||||
authDiskSource.storeUserAutoUnlockKey(
|
||||
userId = mockUserId,
|
||||
userAutoUnlockKey = mockUserAutoUnlockKey,
|
||||
)
|
||||
val actual = fakeEncryptedSharedPreferences
|
||||
.getString(
|
||||
"${userAutoUnlockKeyBaseKey}_$mockUserId",
|
||||
null,
|
||||
)
|
||||
assertEquals(
|
||||
mockUserAutoUnlockKey,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getOrganizationKeys should pull from SharedPreferences`() {
|
||||
val organizationKeysBaseKey = "bwPreferencesStorage:encOrgKeys"
|
||||
|
|
|
@ -21,6 +21,7 @@ class FakeAuthDiskSource : AuthDiskSource {
|
|||
|
||||
private val storedUserKeys = mutableMapOf<String, String?>()
|
||||
private val storedPrivateKeys = mutableMapOf<String, String?>()
|
||||
private val storedUserAutoUnlockKeys = mutableMapOf<String, String?>()
|
||||
private val storedOrganizations =
|
||||
mutableMapOf<String, List<SyncResponseJson.Profile.Organization>?>()
|
||||
private val storedOrganizationKeys = mutableMapOf<String, Map<String, String>?>()
|
||||
|
@ -46,6 +47,13 @@ class FakeAuthDiskSource : AuthDiskSource {
|
|||
storedPrivateKeys[userId] = privateKey
|
||||
}
|
||||
|
||||
override fun getUserAutoUnlockKey(userId: String): String? =
|
||||
storedUserAutoUnlockKeys[userId]
|
||||
|
||||
override fun storeUserAutoUnlockKey(userId: String, userAutoUnlockKey: String?) {
|
||||
storedUserAutoUnlockKeys[userId] = userAutoUnlockKey
|
||||
}
|
||||
|
||||
override fun getOrganizationKeys(
|
||||
userId: String,
|
||||
): Map<String, String>? = storedOrganizationKeys[userId]
|
||||
|
|
Loading…
Add table
Reference in a new issue