PM-39765: bug: Improve error parsing for vault unlock (#7124)

This commit is contained in:
David Perez
2026-07-01 14:03:36 +00:00
committed by GitHub
parent b01067ffd8
commit 0d2fd2d184
2 changed files with 63 additions and 25 deletions
@@ -5,12 +5,14 @@ import com.bitwarden.collections.CollectionId
import com.bitwarden.collections.CollectionView
import com.bitwarden.core.DeriveKeyConnectorException
import com.bitwarden.core.DeriveKeyConnectorRequest
import com.bitwarden.core.EncryptionSettingsException
import com.bitwarden.core.EnrollPinResponse
import com.bitwarden.core.InitOrgCryptoRequest
import com.bitwarden.core.InitUserCryptoRequest
import com.bitwarden.core.UpdateKdfResponse
import com.bitwarden.core.UpdatePasswordResponse
import com.bitwarden.core.data.manager.dispatcher.DispatcherManager
import com.bitwarden.core.data.util.asFailure
import com.bitwarden.crypto.Kdf
import com.bitwarden.crypto.TrustDeviceResponse
import com.bitwarden.exporters.Account
@@ -194,12 +196,32 @@ class VaultSdkSourceImpl(
getClient(userId = userId).crypto().initializeUserCrypto(req = request)
}
InitializeCryptoResult.Success
} catch (exception: BitwardenException) {
// The only truly expected error from the SDK is an incorrect key/password.
InitializeCryptoResult.AuthenticationError(
message = exception.message,
error = exception,
)
} catch (exception: BitwardenException.EncryptionSettings) {
when (val error = exception.v1) {
is EncryptionSettingsException.Crypto,
is EncryptionSettingsException.WrongPin,
-> {
InitializeCryptoResult.AuthenticationError(
message = error.message,
error = error,
)
}
is EncryptionSettingsException.CryptoInitialization,
is EncryptionSettingsException.InvalidUpgradeToken,
is EncryptionSettingsException.KeyConnectorRetrievalFailed,
is EncryptionSettingsException.LocalUserDataKeyInitFailed,
is EncryptionSettingsException.LocalUserDataKeyLoadFailed,
is EncryptionSettingsException.LocalUserDataMigrationFailed,
is EncryptionSettingsException.MissingPrivateKey,
is EncryptionSettingsException.UserIdAlreadySet,
is EncryptionSettingsException.UserKeyStateRetrievalFailed,
is EncryptionSettingsException.UserKeyStateUpdateFailed,
-> {
Timber.w(error, "initializeCrypto error")
return error.asFailure()
}
}
}
}
@@ -209,11 +231,9 @@ class VaultSdkSourceImpl(
): Result<InitializeCryptoResult> =
runCatchingWithLogs {
try {
getClient(userId = userId)
.crypto()
.initializeOrgCrypto(req = request)
getClient(userId = userId).crypto().initializeOrgCrypto(req = request)
InitializeCryptoResult.Success
} catch (exception: BitwardenException) {
} catch (exception: BitwardenException.EncryptionSettings) {
// The only truly expected error from the SDK is for incorrect keys.
InitializeCryptoResult.AuthenticationError(
message = exception.message,
@@ -4,6 +4,7 @@ import com.bitwarden.collections.Collection
import com.bitwarden.collections.CollectionView
import com.bitwarden.core.DeriveKeyConnectorException
import com.bitwarden.core.DeriveKeyConnectorRequest
import com.bitwarden.core.EncryptionSettingsException
import com.bitwarden.core.EnrollPinResponse
import com.bitwarden.core.InitOrgCryptoRequest
import com.bitwarden.core.InitUserCryptoRequest
@@ -554,19 +555,38 @@ class VaultSdkSourceTest {
@Test
@Suppress("MaxLineLength")
fun `initializeUserCrypto with BitwardenException failure should return AuthenticationError with message`() =
fun `initializeUserCrypto with BitwardenException EncryptionSettings MissingPrivateKey failure should return an error result`() =
runBlocking {
val userId = "userId"
val mockInitCryptoRequest = mockk<InitUserCryptoRequest>()
val expectedException = EncryptionSettingsException.MissingPrivateKey("Whoopsy")
val bitwardenException = BitwardenException.EncryptionSettings(v1 = expectedException)
coEvery {
clientCrypto.initializeUserCrypto(req = mockInitCryptoRequest)
} throws bitwardenException
val result = vaultSdkSource.initializeCrypto(
userId = userId,
request = mockInitCryptoRequest,
)
assertEquals(expectedException.asFailure(), result)
coVerify {
clientCrypto.initializeUserCrypto(req = mockInitCryptoRequest)
sdkClientManager.getOrCreateClient(userId = userId)
}
}
@Test
@Suppress("MaxLineLength")
fun `initializeUserCrypto with BitwardenException EncryptionSettings Crypto failure should return AuthenticationError with message`() =
runBlocking {
val userId = "userId"
val mockInitCryptoRequest = mockk<InitUserCryptoRequest>()
val expectedErrorMessage = "Whoopsy"
val expectedException = BitwardenException.Crypto(
CryptoException.InvalidKey(expectedErrorMessage),
)
val expectedException = EncryptionSettingsException.Crypto(expectedErrorMessage)
val bitwardenException = BitwardenException.EncryptionSettings(v1 = expectedException)
coEvery {
clientCrypto.initializeUserCrypto(
req = mockInitCryptoRequest,
)
} throws expectedException
clientCrypto.initializeUserCrypto(req = mockInitCryptoRequest)
} throws bitwardenException
val result = vaultSdkSource.initializeCrypto(
userId = userId,
request = mockInitCryptoRequest,
@@ -581,11 +601,9 @@ class VaultSdkSourceTest {
result,
)
coVerify {
clientCrypto.initializeUserCrypto(
req = mockInitCryptoRequest,
)
clientCrypto.initializeUserCrypto(req = mockInitCryptoRequest)
sdkClientManager.getOrCreateClient(userId = userId)
}
coVerify { sdkClientManager.getOrCreateClient(userId = userId) }
}
@Test
@@ -642,13 +660,13 @@ class VaultSdkSourceTest {
@Test
@Suppress("MaxLineLength")
fun `initializeOrgCrypto with BitwardenException failure should return AuthenticationError with correct message`() =
fun `initializeOrgCrypto with BitwardenException EncryptionSettingsException failure should return AuthenticationError with correct message`() =
runBlocking {
val userId = "userId"
val mockInitCryptoRequest = mockk<InitOrgCryptoRequest>()
val expectedErrorMessage = "Whoopsy2"
val expectedException = BitwardenException.Crypto(
CryptoException.InvalidKey(expectedErrorMessage),
val expectedException = BitwardenException.EncryptionSettings(
v1 = EncryptionSettingsException.Crypto(expectedErrorMessage),
)
coEvery {
clientCrypto.initializeOrgCrypto(