mirror of
https://github.com/bitwarden/android.git
synced 2025-03-15 18:58:59 +03:00
Fix password reset (#896)
This commit is contained in:
parent
27c93d26e5
commit
2c092d9d2c
5 changed files with 99 additions and 71 deletions
|
@ -678,21 +678,21 @@ class AuthRepositoryImpl(
|
|||
onFailure = { return ResetPasswordResult.Error },
|
||||
onSuccess = { it },
|
||||
)
|
||||
return authSdkSource
|
||||
.makeRegisterKeys(
|
||||
email = activeAccount.profile.email,
|
||||
password = newPassword,
|
||||
kdf = activeAccount.profile.toSdkParams(),
|
||||
return vaultSdkSource
|
||||
.updatePassword(
|
||||
userId = activeAccount.profile.userId,
|
||||
newPassword = newPassword,
|
||||
)
|
||||
.flatMap { registerKeyResponse ->
|
||||
accountsService.resetPassword(
|
||||
body = ResetPasswordRequestJson(
|
||||
currentPasswordHash = currentPasswordHash,
|
||||
newPasswordHash = registerKeyResponse.masterPasswordHash,
|
||||
passwordHint = passwordHint,
|
||||
key = registerKeyResponse.encryptedUserKey,
|
||||
),
|
||||
)
|
||||
.flatMap { updatePasswordResponse ->
|
||||
accountsService
|
||||
.resetPassword(
|
||||
body = ResetPasswordRequestJson(
|
||||
currentPasswordHash = currentPasswordHash,
|
||||
newPasswordHash = updatePasswordResponse.passwordHash,
|
||||
passwordHint = passwordHint,
|
||||
key = updatePasswordResponse.newKey,
|
||||
),
|
||||
)
|
||||
}
|
||||
.fold(
|
||||
onSuccess = {
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.bitwarden.core.PasswordHistoryView
|
|||
import com.bitwarden.core.Send
|
||||
import com.bitwarden.core.SendView
|
||||
import com.bitwarden.core.TotpResponse
|
||||
import com.bitwarden.core.UpdatePasswordResponse
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.InitializeCryptoResult
|
||||
|
||||
/**
|
||||
|
@ -312,4 +313,12 @@ interface VaultSdkSource {
|
|||
password: String,
|
||||
passwordHash: String,
|
||||
): Result<Boolean>
|
||||
|
||||
/**
|
||||
* Get the keys needed to update the user's password.
|
||||
*/
|
||||
suspend fun updatePassword(
|
||||
userId: String,
|
||||
newPassword: String,
|
||||
): Result<UpdatePasswordResponse>
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.bitwarden.core.PasswordHistoryView
|
|||
import com.bitwarden.core.Send
|
||||
import com.bitwarden.core.SendView
|
||||
import com.bitwarden.core.TotpResponse
|
||||
import com.bitwarden.core.UpdatePasswordResponse
|
||||
import com.bitwarden.sdk.BitwardenException
|
||||
import com.bitwarden.sdk.Client
|
||||
import com.bitwarden.sdk.ClientVault
|
||||
|
@ -329,6 +330,15 @@ class VaultSdkSourceImpl(
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun updatePassword(
|
||||
userId: String,
|
||||
newPassword: String,
|
||||
): Result<UpdatePasswordResponse> = runCatching {
|
||||
getClient(userId = userId)
|
||||
.crypto()
|
||||
.updatePassword(newPassword)
|
||||
}
|
||||
|
||||
private fun getClient(
|
||||
userId: String,
|
||||
): Client = sdkClientManager.getOrCreateClient(userId = userId)
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.repository
|
|||
import app.cash.turbine.test
|
||||
import com.bitwarden.core.AuthRequestResponse
|
||||
import com.bitwarden.core.RegisterKeyResponse
|
||||
import com.bitwarden.core.UpdatePasswordResponse
|
||||
import com.bitwarden.crypto.HashPurpose
|
||||
import com.bitwarden.crypto.Kdf
|
||||
import com.bitwarden.crypto.RsaKeyPair
|
||||
|
@ -1984,7 +1985,9 @@ class AuthRepositoryTest {
|
|||
fun `resetPassword Success should return Success`() = runTest {
|
||||
val currentPassword = "currentPassword"
|
||||
val currentPasswordHash = "hashedCurrentPassword"
|
||||
val password = "password"
|
||||
val newPassword = "newPassword"
|
||||
val newPasswordHash = "newPasswordHash"
|
||||
val newKey = "newKey"
|
||||
fakeAuthDiskSource.userState = SINGLE_USER_STATE_1
|
||||
coEvery {
|
||||
authSdkSource.hashPassword(
|
||||
|
@ -1995,35 +1998,38 @@ class AuthRepositoryTest {
|
|||
)
|
||||
} returns currentPasswordHash.asSuccess()
|
||||
coEvery {
|
||||
authSdkSource.makeRegisterKeys(
|
||||
email = ACCOUNT_1.profile.email,
|
||||
password = password,
|
||||
kdf = ACCOUNT_1.profile.toSdkParams(),
|
||||
vaultSdkSource.updatePassword(
|
||||
userId = ACCOUNT_1.profile.userId,
|
||||
newPassword = newPassword,
|
||||
)
|
||||
} returns Result.success(
|
||||
RegisterKeyResponse(
|
||||
masterPasswordHash = PASSWORD_HASH,
|
||||
encryptedUserKey = ENCRYPTED_USER_KEY,
|
||||
keys = RsaKeyPair(
|
||||
public = PUBLIC_KEY,
|
||||
private = PRIVATE_KEY,
|
||||
),
|
||||
UpdatePasswordResponse(
|
||||
passwordHash = newPasswordHash,
|
||||
newKey = newKey,
|
||||
),
|
||||
)
|
||||
coEvery {
|
||||
accountsService.resetPassword(
|
||||
body = ResetPasswordRequestJson(
|
||||
currentPasswordHash = currentPasswordHash,
|
||||
newPasswordHash = PASSWORD_HASH,
|
||||
newPasswordHash = newPasswordHash,
|
||||
passwordHint = null,
|
||||
key = ENCRYPTED_USER_KEY,
|
||||
key = newKey,
|
||||
),
|
||||
)
|
||||
} returns Unit.asSuccess()
|
||||
coEvery {
|
||||
authSdkSource.hashPassword(
|
||||
email = ACCOUNT_1.profile.email,
|
||||
password = newPassword,
|
||||
kdf = ACCOUNT_1.profile.toSdkParams(),
|
||||
purpose = HashPurpose.LOCAL_AUTHORIZATION,
|
||||
)
|
||||
} returns newPasswordHash.asSuccess()
|
||||
|
||||
val result = repository.resetPassword(
|
||||
currentPassword = currentPassword,
|
||||
newPassword = password,
|
||||
newPassword = newPassword,
|
||||
passwordHint = null,
|
||||
)
|
||||
|
||||
|
@ -2032,23 +2038,28 @@ class AuthRepositoryTest {
|
|||
result,
|
||||
)
|
||||
coVerify {
|
||||
authSdkSource.makeRegisterKeys(
|
||||
authSdkSource.hashPassword(
|
||||
email = ACCOUNT_1.profile.email,
|
||||
password = password,
|
||||
password = currentPassword,
|
||||
kdf = ACCOUNT_1.profile.toSdkParams(),
|
||||
purpose = HashPurpose.SERVER_AUTHORIZATION,
|
||||
)
|
||||
vaultSdkSource.updatePassword(
|
||||
userId = ACCOUNT_1.profile.userId,
|
||||
newPassword = newPassword,
|
||||
)
|
||||
accountsService.resetPassword(
|
||||
body = ResetPasswordRequestJson(
|
||||
currentPasswordHash = currentPasswordHash,
|
||||
newPasswordHash = PASSWORD_HASH,
|
||||
newPasswordHash = newPasswordHash,
|
||||
passwordHint = null,
|
||||
key = ENCRYPTED_USER_KEY,
|
||||
key = newKey,
|
||||
),
|
||||
)
|
||||
}
|
||||
fakeAuthDiskSource.assertMasterPasswordHash(
|
||||
userId = USER_ID_1,
|
||||
passwordHash = PASSWORD_HASH,
|
||||
passwordHash = newPasswordHash,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -2056,7 +2067,7 @@ class AuthRepositoryTest {
|
|||
fun `resetPassword Failure should return Error`() = runTest {
|
||||
val currentPassword = "currentPassword"
|
||||
val currentPasswordHash = "hashedCurrentPassword"
|
||||
val password = "password"
|
||||
val newPassword = "newPassword"
|
||||
fakeAuthDiskSource.userState = SINGLE_USER_STATE_1
|
||||
coEvery {
|
||||
authSdkSource.hashPassword(
|
||||
|
@ -2067,35 +2078,15 @@ class AuthRepositoryTest {
|
|||
)
|
||||
} returns currentPasswordHash.asSuccess()
|
||||
coEvery {
|
||||
authSdkSource.makeRegisterKeys(
|
||||
email = ACCOUNT_1.profile.email,
|
||||
password = password,
|
||||
kdf = ACCOUNT_1.profile.toSdkParams(),
|
||||
)
|
||||
} returns Result.success(
|
||||
RegisterKeyResponse(
|
||||
masterPasswordHash = PASSWORD_HASH,
|
||||
encryptedUserKey = ENCRYPTED_USER_KEY,
|
||||
keys = RsaKeyPair(
|
||||
public = PUBLIC_KEY,
|
||||
private = PRIVATE_KEY,
|
||||
),
|
||||
),
|
||||
)
|
||||
coEvery {
|
||||
accountsService.resetPassword(
|
||||
body = ResetPasswordRequestJson(
|
||||
currentPasswordHash = currentPasswordHash,
|
||||
newPasswordHash = PASSWORD_HASH,
|
||||
passwordHint = null,
|
||||
key = ENCRYPTED_USER_KEY,
|
||||
),
|
||||
vaultSdkSource.updatePassword(
|
||||
userId = ACCOUNT_1.profile.userId,
|
||||
newPassword = newPassword,
|
||||
)
|
||||
} returns Throwable("Fail").asFailure()
|
||||
|
||||
val result = repository.resetPassword(
|
||||
currentPassword = currentPassword,
|
||||
newPassword = password,
|
||||
newPassword = newPassword,
|
||||
passwordHint = null,
|
||||
)
|
||||
|
||||
|
@ -2110,18 +2101,9 @@ class AuthRepositoryTest {
|
|||
kdf = ACCOUNT_1.profile.toSdkParams(),
|
||||
purpose = HashPurpose.SERVER_AUTHORIZATION,
|
||||
)
|
||||
authSdkSource.makeRegisterKeys(
|
||||
email = ACCOUNT_1.profile.email,
|
||||
password = password,
|
||||
kdf = ACCOUNT_1.profile.toSdkParams(),
|
||||
)
|
||||
accountsService.resetPassword(
|
||||
body = ResetPasswordRequestJson(
|
||||
currentPasswordHash = currentPasswordHash,
|
||||
newPasswordHash = PASSWORD_HASH,
|
||||
passwordHint = null,
|
||||
key = ENCRYPTED_USER_KEY,
|
||||
),
|
||||
vaultSdkSource.updatePassword(
|
||||
userId = ACCOUNT_1.profile.userId,
|
||||
newPassword = newPassword,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.bitwarden.core.PasswordHistoryView
|
|||
import com.bitwarden.core.Send
|
||||
import com.bitwarden.core.SendView
|
||||
import com.bitwarden.core.TotpResponse
|
||||
import com.bitwarden.core.UpdatePasswordResponse
|
||||
import com.bitwarden.sdk.BitwardenException
|
||||
import com.bitwarden.sdk.Client
|
||||
import com.bitwarden.sdk.ClientAuth
|
||||
|
@ -762,4 +763,30 @@ class VaultSdkSourceTest {
|
|||
result,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `updatePassword should call SDK and a Result with correct data`() = runTest {
|
||||
val userId = "userId"
|
||||
val newPassword = "newPassword"
|
||||
val passwordHash = "passwordHash"
|
||||
val newKey = "newKey"
|
||||
val updatePasswordResponse = UpdatePasswordResponse(
|
||||
passwordHash = passwordHash,
|
||||
newKey = newKey,
|
||||
)
|
||||
coEvery {
|
||||
clientCrypto.updatePassword(
|
||||
newPassword = newPassword,
|
||||
)
|
||||
} returns updatePasswordResponse
|
||||
|
||||
val result = vaultSdkSource.updatePassword(
|
||||
userId = userId,
|
||||
newPassword = newPassword,
|
||||
)
|
||||
assertEquals(
|
||||
updatePasswordResponse.asSuccess(),
|
||||
result,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue