mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 07:05:35 +03:00
Add stored pending auth request (#1204)
This commit is contained in:
parent
0cc28e41ba
commit
2185d3847a
5 changed files with 135 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
|||
package com.x8bit.bitwarden.data.auth.datasource.disk
|
||||
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.PendingAuthRequestJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -121,6 +122,19 @@ interface AuthDiskSource {
|
|||
*/
|
||||
fun storeDeviceKey(userId: String, deviceKey: String?)
|
||||
|
||||
/**
|
||||
* Gets the stored [PendingAuthRequestJson] for the given [userId].
|
||||
*/
|
||||
fun getPendingAuthRequest(userId: String): PendingAuthRequestJson?
|
||||
|
||||
/**
|
||||
* Stores the [PendingAuthRequestJson] for the given [userId].
|
||||
*/
|
||||
fun storePendingAuthRequest(
|
||||
userId: String,
|
||||
pendingAuthRequest: PendingAuthRequestJson?,
|
||||
)
|
||||
|
||||
/**
|
||||
* Gets the biometrics key for the given [userId].
|
||||
*/
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.datasource.disk
|
|||
|
||||
import android.content.SharedPreferences
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.PendingAuthRequestJson
|
||||
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
|
||||
|
@ -21,6 +22,7 @@ private const val ACCOUNT_TOKENS_KEY = "$ENCRYPTED_BASE_KEY:accountTokens"
|
|||
private const val BIOMETRICS_UNLOCK_KEY = "$ENCRYPTED_BASE_KEY:userKeyBiometricUnlock"
|
||||
private const val USER_AUTO_UNLOCK_KEY_KEY = "$ENCRYPTED_BASE_KEY:userKeyAutoUnlock"
|
||||
private const val DEVICE_KEY_KEY = "$ENCRYPTED_BASE_KEY:deviceKey"
|
||||
private const val PENDING_ADMIN_AUTH_REQUEST_KEY = "$ENCRYPTED_BASE_KEY:pendingAdminAuthRequest"
|
||||
|
||||
private const val UNIQUE_APP_ID_KEY = "$BASE_KEY:appId"
|
||||
private const val REMEMBERED_EMAIL_ADDRESS_KEY = "$BASE_KEY:rememberedEmail"
|
||||
|
@ -125,6 +127,7 @@ class AuthDiskSourceImpl(
|
|||
storeOrganizationKeys(userId = userId, organizationKeys = null)
|
||||
storeOrganizations(userId = userId, organizations = null)
|
||||
storeDeviceKey(userId = userId, deviceKey = null)
|
||||
storePendingAuthRequest(userId = userId, pendingAuthRequest = null)
|
||||
storeUserBiometricUnlockKey(userId = userId, biometricsKey = null)
|
||||
storeMasterPasswordHash(userId = userId, passwordHash = null)
|
||||
storePolicies(userId = userId, policies = null)
|
||||
|
@ -201,6 +204,22 @@ class AuthDiskSourceImpl(
|
|||
putEncryptedString(key = "${DEVICE_KEY_KEY}_$userId", value = deviceKey)
|
||||
}
|
||||
|
||||
override fun getPendingAuthRequest(
|
||||
userId: String,
|
||||
): PendingAuthRequestJson? =
|
||||
getEncryptedString(key = "${PENDING_ADMIN_AUTH_REQUEST_KEY}_$userId")
|
||||
?.let { json.decodeFromStringOrNull(it) }
|
||||
|
||||
override fun storePendingAuthRequest(
|
||||
userId: String,
|
||||
pendingAuthRequest: PendingAuthRequestJson?,
|
||||
) {
|
||||
putEncryptedString(
|
||||
key = "${PENDING_ADMIN_AUTH_REQUEST_KEY}_$userId",
|
||||
value = pendingAuthRequest?.let { json.encodeToString(it) },
|
||||
)
|
||||
}
|
||||
|
||||
override fun getUserBiometricUnlockKey(userId: String): String? =
|
||||
getEncryptedString(key = "${BIOMETRICS_UNLOCK_KEY}_$userId")
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.x8bit.bitwarden.data.auth.datasource.disk.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Container for the user's API tokens.
|
||||
*
|
||||
* @property requestId The ID of the pending Auth Request.
|
||||
* @property requestPrivateKey The private of the pending Auth Request.
|
||||
*/
|
||||
@Serializable
|
||||
data class PendingAuthRequestJson(
|
||||
@SerialName("Id")
|
||||
val requestId: String,
|
||||
|
||||
@SerialName("PrivateKey")
|
||||
val requestPrivateKey: String,
|
||||
)
|
|
@ -6,6 +6,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
|
|||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.ForcePasswordResetReason
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.PendingAuthRequestJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.KdfTypeJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorUserDecryptionOptionsJson
|
||||
|
@ -185,6 +186,13 @@ class AuthDiskSourceTest {
|
|||
userId = userId,
|
||||
deviceKey = "9876-5432-1234",
|
||||
)
|
||||
authDiskSource.storePendingAuthRequest(
|
||||
userId = userId,
|
||||
pendingAuthRequest = PendingAuthRequestJson(
|
||||
requestId = "12345",
|
||||
requestPrivateKey = "67890",
|
||||
),
|
||||
)
|
||||
authDiskSource.storeUserBiometricUnlockKey(
|
||||
userId = userId,
|
||||
biometricsKey = "1234-9876-0192",
|
||||
|
@ -226,6 +234,7 @@ class AuthDiskSourceTest {
|
|||
authDiskSource.clearData(userId = userId)
|
||||
|
||||
assertNull(authDiskSource.getDeviceKey(userId = userId))
|
||||
assertNull(authDiskSource.getPendingAuthRequest(userId = userId))
|
||||
assertNull(authDiskSource.getUserBiometricUnlockKey(userId = userId))
|
||||
assertNull(authDiskSource.getLastActiveTimeMillis(userId = userId))
|
||||
assertNull(authDiskSource.getInvalidUnlockAttempts(userId = userId))
|
||||
|
@ -542,6 +551,60 @@ class AuthDiskSourceTest {
|
|||
assertFalse(fakeEncryptedSharedPreferences.contains(deviceKeyKey))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPendingAuthRequest should pull from SharedPreferences`() {
|
||||
val pendingAdminAuthRequestBaseKey = "bwSecureStorage:pendingAdminAuthRequest"
|
||||
val mockUserId = "mockUserId"
|
||||
val pendingAdminAuthRequestKey = "${pendingAdminAuthRequestBaseKey}_$mockUserId"
|
||||
fakeEncryptedSharedPreferences.edit {
|
||||
putString(
|
||||
pendingAdminAuthRequestKey,
|
||||
"""
|
||||
{
|
||||
"Id": "12345",
|
||||
"PrivateKey": "67890"
|
||||
}
|
||||
""",
|
||||
)
|
||||
}
|
||||
val actual = authDiskSource.getPendingAuthRequest(userId = mockUserId)
|
||||
assertEquals(
|
||||
PendingAuthRequestJson(requestId = "12345", requestPrivateKey = "67890"),
|
||||
actual,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `storePendingAuthRequest for non-null values should update SharedPreferences`() {
|
||||
val pendingAdminAuthRequestKeyBaseKey = "bwSecureStorage:pendingAdminAuthRequest"
|
||||
val mockUserId = "mockUserId"
|
||||
val pendingAuthRequestKey = "${pendingAdminAuthRequestKeyBaseKey}_$mockUserId"
|
||||
val pendingAdminAuthRequest = PendingAuthRequestJson(
|
||||
requestId = "12345",
|
||||
requestPrivateKey = "67890",
|
||||
)
|
||||
authDiskSource.storePendingAuthRequest(
|
||||
userId = mockUserId,
|
||||
pendingAuthRequest = pendingAdminAuthRequest,
|
||||
)
|
||||
val actual = fakeEncryptedSharedPreferences.getString(
|
||||
key = pendingAuthRequestKey,
|
||||
defaultValue = null,
|
||||
)
|
||||
assertEquals(
|
||||
json.parseToJsonElement(
|
||||
"""
|
||||
{
|
||||
"Id": "12345",
|
||||
"PrivateKey": "67890"
|
||||
}
|
||||
"""
|
||||
.trimIndent(),
|
||||
),
|
||||
json.parseToJsonElement(requireNotNull(actual)),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getUserBiometricUnlockKey should pull from SharedPreferences`() {
|
||||
val biometricsKeyBaseKey = "bwSecureStorage:userKeyBiometricUnlock"
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.datasource.disk.util
|
|||
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.PendingAuthRequestJson
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
|
@ -38,6 +39,7 @@ class FakeAuthDiskSource : AuthDiskSource {
|
|||
private val storedOrganizationKeys = mutableMapOf<String, Map<String, String>?>()
|
||||
private val storedAccountTokens = mutableMapOf<String, AccountTokensJson?>()
|
||||
private val storedDeviceKey = mutableMapOf<String, String?>()
|
||||
private val storedPendingAuthRequests = mutableMapOf<String, PendingAuthRequestJson?>()
|
||||
private val storedBiometricKeys = mutableMapOf<String, String?>()
|
||||
private val storedMasterPasswordHashes = mutableMapOf<String, String?>()
|
||||
private val storedPolicies = mutableMapOf<String, List<SyncResponseJson.Policy>?>()
|
||||
|
@ -65,6 +67,7 @@ class FakeAuthDiskSource : AuthDiskSource {
|
|||
storedOrganizations.remove(userId)
|
||||
storedPolicies.remove(userId)
|
||||
storedAccountTokens.remove(userId)
|
||||
storedPendingAuthRequests.remove(userId)
|
||||
storedBiometricKeys.remove(userId)
|
||||
storedOrganizationKeys.remove(userId)
|
||||
|
||||
|
@ -170,6 +173,16 @@ class FakeAuthDiskSource : AuthDiskSource {
|
|||
storedDeviceKey[userId] = deviceKey
|
||||
}
|
||||
|
||||
override fun getPendingAuthRequest(userId: String): PendingAuthRequestJson? =
|
||||
storedPendingAuthRequests[userId]
|
||||
|
||||
override fun storePendingAuthRequest(
|
||||
userId: String,
|
||||
pendingAuthRequest: PendingAuthRequestJson?,
|
||||
) {
|
||||
storedPendingAuthRequests[userId] = pendingAuthRequest
|
||||
}
|
||||
|
||||
override fun getUserBiometricUnlockKey(userId: String): String? =
|
||||
storedBiometricKeys[userId]
|
||||
|
||||
|
@ -289,6 +302,13 @@ class FakeAuthDiskSource : AuthDiskSource {
|
|||
assertEquals(deviceKey, storedDeviceKey[userId])
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the [pendingAuthRequest] was stored successfully using the [userId].
|
||||
*/
|
||||
fun assertPendingAuthRequest(userId: String, pendingAuthRequest: PendingAuthRequestJson?) {
|
||||
assertEquals(pendingAuthRequest, storedPendingAuthRequests[userId])
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the [biometricsKey] was stored successfully using the [userId].
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue