[PM-28271] Rename validatePin to validatePinUserKey and update SDK usage (#6323)

This commit is contained in:
Patrick Honkonen
2026-01-05 22:08:21 +00:00
committed by GitHub
parent 05d003edb2
commit 29d84d69f5
10 changed files with 102 additions and 89 deletions
@@ -359,14 +359,14 @@ interface AuthRepository :
suspend fun getPasswordStrength(email: String? = null, password: String): PasswordStrengthResult
/**
* Validates the master password for the current logged in user.
* Validates the master password for the current logged-in user.
*/
suspend fun validatePassword(password: String): ValidatePasswordResult
/**
* Validates the PIN for the current logged in user.
* Validates the PIN for the current logged-in user.
*/
suspend fun validatePin(pin: String): ValidatePinResult
suspend fun validatePinUserKey(pin: String): ValidatePinResult
/**
* Validates the given [password] against the master password
@@ -1296,7 +1296,7 @@ class AuthRepositoryImpl(
}
}
override suspend fun validatePin(pin: String): ValidatePinResult {
override suspend fun validatePinUserKey(pin: String): ValidatePinResult {
val activeAccount = authDiskSource
.userState
?.activeAccount
@@ -1305,13 +1305,13 @@ class AuthRepositoryImpl(
val pinProtectedUserKeyEnvelope = authDiskSource
.getPinProtectedUserKeyEnvelope(userId = activeAccount.userId)
?: return ValidatePinResult.Error(
error = MissingPropertyException("Pin Protected User Key"),
error = MissingPropertyException("Pin Protected User Key Envelope"),
)
return vaultSdkSource
.validatePin(
.validatePinUserKey(
userId = activeAccount.userId,
pin = pin,
pinProtectedUserKey = pinProtectedUserKeyEnvelope,
pinProtectedUserKeyEnvelope = pinProtectedUserKeyEnvelope,
)
.fold(
onSuccess = { ValidatePinResult.Success(isValid = it) },
@@ -97,12 +97,13 @@ interface VaultSdkSource {
): Result<EnrollPinResponse>
/**
* Validate the user pin using the [pinProtectedUserKey].
* Validates that the given PIN with the encrypted user key and returns `true` if the PIN is
* correct, otherwise `false`.
*/
suspend fun validatePin(
suspend fun validatePinUserKey(
userId: String,
pin: String,
pinProtectedUserKey: String,
pinProtectedUserKeyEnvelope: String,
): Result<Boolean>
/**
@@ -100,6 +100,7 @@ class VaultSdkSourceImpl(
is DeriveKeyConnectorException.WrongPassword -> {
DeriveKeyConnectorResult.WrongPasswordError
}
is DeriveKeyConnectorException.Crypto -> {
DeriveKeyConnectorResult.Error(error = ex)
}
@@ -129,15 +130,18 @@ class VaultSdkSourceImpl(
.enrollPinWithEncryptedPin(encryptedPin = encryptedPin)
}
override suspend fun validatePin(
override suspend fun validatePinUserKey(
userId: String,
pin: String,
pinProtectedUserKey: String,
pinProtectedUserKeyEnvelope: String,
): Result<Boolean> =
runCatchingWithLogs {
getClient(userId = userId)
.auth()
.validatePin(pin = pin, pinProtectedUserKey = pinProtectedUserKey)
.validatePinProtectedUserKeyEnvelope(
pin = pin,
pinProtectedUserKeyEnvelope = pinProtectedUserKeyEnvelope,
)
}
override suspend fun getAuthRequestKey(
@@ -734,7 +734,7 @@ class VaultAddEditViewModel @Inject constructor(
action: VaultAddEditAction.Common.PinFido2VerificationSubmit,
) {
viewModelScope.launch {
val result = authRepository.validatePin(action.pin)
val result = authRepository.validatePinUserKey(action.pin)
sendAction(
VaultAddEditAction.Internal.ValidateFido2PinResultReceive(
result = result,
@@ -542,7 +542,7 @@ class VaultItemListingViewModel @Inject constructor(
action: VaultItemListingsAction.PinUserVerificationSubmit,
) {
viewModelScope.launch {
val result = authRepository.validatePin(action.pin)
val result = authRepository.validatePinUserKey(action.pin)
sendAction(
VaultItemListingsAction.Internal.ValidateUserVerificationPinResultReceive(
result = result,
@@ -6767,7 +6767,7 @@ class AuthRepositoryTest {
val pin = "PIN"
fakeAuthDiskSource.userState = null
val result = repository.validatePin(pin = pin)
val result = repository.validatePinUserKey(pin = pin)
assertEquals(
ValidatePinResult.Error(error = NoActiveUserException()),
@@ -6775,8 +6775,9 @@ class AuthRepositoryTest {
)
}
@Suppress("MaxLineLength")
@Test
fun `validatePin returns ValidatePinResult Error when no pin protected user key found`() =
fun `validatePinUserKey returns ValidatePinResult Error when no pin protected user key found`() =
runTest {
val pin = "PIN"
fakeAuthDiskSource.userState = SINGLE_USER_STATE_1
@@ -6785,7 +6786,7 @@ class AuthRepositoryTest {
pinProtectedUserKey = null,
)
val result = repository.validatePin(pin = pin)
val result = repository.validatePinUserKey(pin = pin)
assertEquals(
ValidatePinResult.Error(MissingPropertyException("Pin Protected User Key")),
@@ -6794,75 +6795,42 @@ class AuthRepositoryTest {
}
@Test
fun `validatePin returns ValidatePinResult Error when SDK validatePin fails`() = runTest {
val pin = "PIN"
val pinProtectedUserKey = "pinProtectedUserKey"
val error = Throwable("Fail!")
fakeAuthDiskSource.userState = SINGLE_USER_STATE_1
fakeAuthDiskSource.storePinProtectedUserKeyEnvelope(
userId = SINGLE_USER_STATE_1.activeUserId,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
coEvery {
vaultSdkSource.validatePin(
userId = SINGLE_USER_STATE_1.activeUserId,
pin = pin,
pinProtectedUserKey = pinProtectedUserKey,
)
} returns error.asFailure()
val result = repository.validatePin(pin = pin)
assertEquals(
ValidatePinResult.Error(error = error),
result,
)
coVerify(exactly = 1) {
vaultSdkSource.validatePin(
userId = SINGLE_USER_STATE_1.activeUserId,
pin = pin,
pinProtectedUserKey = pinProtectedUserKey,
)
}
}
@Suppress("MaxLineLength")
@Test
fun `validatePin returns ValidatePinResult Success with valid false when SDK validatePin returns false`() =
fun `validatePinUserKey returns ValidatePinResult Error when SDK validatePin fails`() =
runTest {
val pin = "PIN"
val pinProtectedUserKey = "pinProtectedUserKey"
val error = Throwable("Fail!")
fakeAuthDiskSource.userState = SINGLE_USER_STATE_1
fakeAuthDiskSource.storePinProtectedUserKeyEnvelope(
userId = SINGLE_USER_STATE_1.activeUserId,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
coEvery {
vaultSdkSource.validatePin(
vaultSdkSource.validatePinUserKey(
userId = SINGLE_USER_STATE_1.activeUserId,
pin = pin,
pinProtectedUserKey = pinProtectedUserKey,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
} returns false.asSuccess()
} returns error.asFailure()
val result = repository.validatePin(pin = pin)
val result = repository.validatePinUserKey(pin = pin)
assertEquals(
ValidatePinResult.Success(isValid = false),
ValidatePinResult.Error(error = error),
result,
)
coVerify(exactly = 1) {
vaultSdkSource.validatePin(
vaultSdkSource.validatePinUserKey(
userId = SINGLE_USER_STATE_1.activeUserId,
pin = pin,
pinProtectedUserKey = pinProtectedUserKey,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
}
}
@Suppress("MaxLineLength")
@Test
fun `validatePin returns ValidatePinResult Success with valid true when SDK validatePin returns true`() =
fun `validatePinUserKey returns ValidatePinResult Success with valid false when SDK validatePin returns false`() =
runTest {
val pin = "PIN"
val pinProtectedUserKey = "pinProtectedUserKey"
@@ -6872,24 +6840,58 @@ class AuthRepositoryTest {
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
coEvery {
vaultSdkSource.validatePin(
vaultSdkSource.validatePinUserKey(
userId = SINGLE_USER_STATE_1.activeUserId,
pin = pin,
pinProtectedUserKey = pinProtectedUserKey,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
} returns false.asSuccess()
val result = repository.validatePinUserKey(pin = pin)
assertEquals(
ValidatePinResult.Success(isValid = false),
result,
)
coVerify(exactly = 1) {
vaultSdkSource.validatePinUserKey(
userId = SINGLE_USER_STATE_1.activeUserId,
pin = pin,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
}
}
@Suppress("MaxLineLength")
@Test
fun `validatePinUserKey returns ValidatePinResult Success with valid true when SDK validatePin returns true`() =
runTest {
val pin = "PIN"
val pinProtectedUserKey = "pinProtectedUserKey"
fakeAuthDiskSource.userState = SINGLE_USER_STATE_1
fakeAuthDiskSource.storePinProtectedUserKeyEnvelope(
userId = SINGLE_USER_STATE_1.activeUserId,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
coEvery {
vaultSdkSource.validatePinUserKey(
userId = SINGLE_USER_STATE_1.activeUserId,
pin = pin,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
} returns true.asSuccess()
val result = repository.validatePin(pin = pin)
val result = repository.validatePinUserKey(pin = pin)
assertEquals(
ValidatePinResult.Success(isValid = true),
result,
)
coVerify(exactly = 1) {
vaultSdkSource.validatePin(
vaultSdkSource.validatePinUserKey(
userId = SINGLE_USER_STATE_1.activeUserId,
pin = pin,
pinProtectedUserKey = pinProtectedUserKey,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
}
}
@@ -384,25 +384,31 @@ class VaultSdkSourceTest {
}
@Test
fun `validatePin should call SDK and return a Result with the correct data`() =
fun `validatePinUserKey should call SDK and return a Result with the correct data`() =
runBlocking {
val userId = "userId"
val pin = "pin"
val pinProtectedUserKey = "pinProtectedUserKey"
val expectedResult = true
coEvery {
clientAuth.validatePin(pin = pin, pinProtectedUserKey = pinProtectedUserKey)
clientAuth.validatePinProtectedUserKeyEnvelope(
pin = pin,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
} returns expectedResult
val result = vaultSdkSource.validatePin(
val result = vaultSdkSource.validatePinUserKey(
userId = userId,
pin = pin,
pinProtectedUserKey = pinProtectedUserKey,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
assertEquals(expectedResult.asSuccess(), result)
coVerify(exactly = 1) {
clientAuth.validatePin(pin = pin, pinProtectedUserKey = pinProtectedUserKey)
clientAuth.validatePinProtectedUserKeyEnvelope(
pin = pin,
pinProtectedUserKeyEnvelope = pinProtectedUserKey,
)
sdkClientManager.getOrCreateClient(userId = userId)
}
}
@@ -4242,7 +4242,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
fun `PinFido2VerificationSubmit should display CredentialError when Pin verification fails`() {
val pin = "PIN"
coEvery {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
} returns ValidatePinResult.Error(error = Throwable("Fail!"))
viewModel.trySendAction(
@@ -4259,7 +4259,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.value.dialog,
)
coVerify {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
}
}
@@ -4268,7 +4268,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
fun `PinFido2VerificationSubmit should display Fido2PinError when user has retries remaining`() {
val pin = "PIN"
coEvery {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
} returns ValidatePinResult.Success(isValid = false)
viewModel.trySendAction(
@@ -4282,7 +4282,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.value.dialog,
)
coVerify {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
}
}
@@ -4292,7 +4292,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val pin = "PIN"
every { bitwardenCredentialManager.hasAuthenticationAttemptsRemaining() } returns false
coEvery {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
} returns ValidatePinResult.Success(isValid = false)
viewModel.trySendAction(
@@ -4309,7 +4309,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.value.dialog,
)
coVerify {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
}
}
@@ -4318,7 +4318,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
fun `PinFido2VerificationSubmit should register credential when pin authenticated successfully`() {
val pin = "PIN"
coEvery {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
} returns ValidatePinResult.Success(isValid = true)
viewModel.trySendAction(
@@ -4327,7 +4327,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
),
)
coVerify {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
}
}
@@ -4734,7 +4734,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
val selectedCipherId = "selectedCipherId"
val pin = "PIN"
coEvery {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
} returns ValidatePinResult.Error(error = Throwable("Fail!"))
viewModel.trySendAction(
@@ -4754,7 +4754,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.value.dialogState,
)
coVerify {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
}
}
@@ -4765,7 +4765,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
val selectedCipherId = "selectedCipherId"
val pin = "PIN"
coEvery {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
} returns ValidatePinResult.Success(isValid = false)
viewModel.trySendAction(
@@ -4784,7 +4784,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.value.dialogState,
)
coVerify {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
}
}
@@ -4796,7 +4796,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
val pin = "PIN"
every { bitwardenCredentialManager.hasAuthenticationAttemptsRemaining() } returns false
coEvery {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
} returns ValidatePinResult.Success(isValid = false)
viewModel.trySendAction(
@@ -4816,7 +4816,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.value.dialogState,
)
coVerify {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
}
}
@@ -4827,7 +4827,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
val selectedCipherId = "selectedCipherId"
val pin = "PIN"
coEvery {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
} returns ValidatePinResult.Success(isValid = true)
coEvery {
vaultRepository.getCipher("selectedCipherId")
@@ -4850,7 +4850,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.value.dialogState,
)
coVerify {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
}
}
@@ -4874,7 +4874,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
),
)
coEvery {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
} returns ValidatePinResult.Success(isValid = true)
viewModel.trySendAction(
@@ -4884,7 +4884,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
),
)
coVerify {
authRepository.validatePin(pin = pin)
authRepository.validatePinUserKey(pin = pin)
}
}