Set the TDE reason for a forced password reset (#1167)

This commit is contained in:
David Perez 2024-03-21 15:49:27 -05:00 committed by Álison Fernandes
parent 0791d787e0
commit dc4b61c503
2 changed files with 77 additions and 23 deletions

View file

@ -17,8 +17,7 @@ fun GetTokenResponseJson.Success.toUserState(
previousUserState: UserStateJson?,
environmentUrlData: EnvironmentUrlDataJson,
): UserStateJson {
val accessToken = this.accessToken
val jwtTokenData = requireNotNull(parseJwtTokenDataOrNull(jwtToken = accessToken))
val jwtTokenData = requireNotNull(parseJwtTokenDataOrNull(jwtToken = this.accessToken))
val userId = jwtTokenData.userId
val account = AccountJson(
@ -31,11 +30,7 @@ fun GetTokenResponseJson.Success.toUserState(
organizationId = null,
avatarColorHex = null,
hasPremium = jwtTokenData.hasPremium,
forcePasswordResetReason = if (this.shouldForcePasswordReset) {
ForcePasswordResetReason.ADMIN_FORCE_PASSWORD_RESET
} else {
null
},
forcePasswordResetReason = this.toForcePasswordResetReason(),
kdfType = this.kdfType,
kdfIterations = this.kdfIterations,
kdfMemory = this.kdfMemory,
@ -63,3 +58,20 @@ fun GetTokenResponseJson.Success.toUserState(
accounts = mapOf(userId to account),
)
}
/**
* Determines the [ForcePasswordResetReason] from the [GetTokenResponseJson.Success].
*/
private fun GetTokenResponseJson.Success.toForcePasswordResetReason(): ForcePasswordResetReason? =
this
.userDecryptionOptions
?.trustedDeviceUserDecryptionOptions
?.let { options ->
ForcePasswordResetReason.TDE_USER_WITHOUT_PASSWORD_HAS_PASSWORD_RESET_PERMISSION
.takeIf {
!this.userDecryptionOptions.hasMasterPassword &&
options.hasManageResetPasswordPermission
}
}
?: ForcePasswordResetReason.ADMIN_FORCE_PASSWORD_RESET
.takeIf { this.shouldForcePasswordReset }

View file

@ -2,9 +2,12 @@ package com.x8bit.bitwarden.data.auth.repository.util
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
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.UserStateJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.GetTokenResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.KdfTypeJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceUserDecryptionOptionsJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.UserDecryptionOptionsJson
import com.x8bit.bitwarden.data.auth.repository.model.JwtTokenDataJson
import io.mockk.every
import io.mockk.mockkStatic
@ -51,6 +54,33 @@ class GetTokenResponseExtensionsTest {
),
)
}
@Test
fun `toUserState with userDecryptionOptions creates a new single user state`() {
val tokenResponse = GET_TOKEN_RESPONSE_SUCCESS.copy(
userDecryptionOptions = USER_DECRYPTION_OPTIONS,
)
val expectedState = SINGLE_USER_STATE_1.copy(
accounts = mapOf(
USER_ID_1 to ACCOUNT_1.copy(
profile = PROFILE_1.copy(
forcePasswordResetReason = ForcePasswordResetReason
.TDE_USER_WITHOUT_PASSWORD_HAS_PASSWORD_RESET_PERMISSION,
userDecryptionOptions = USER_DECRYPTION_OPTIONS,
),
),
),
)
every { parseJwtTokenDataOrNull(ACCESS_TOKEN_1) } returns JWT_TOKEN_DATA
assertEquals(
expectedState,
tokenResponse.toUserState(
previousUserState = null,
environmentUrlData = EnvironmentUrlDataJson.DEFAULT_US,
),
)
}
}
private const val ACCESS_TOKEN_1 = "accessToken1"
@ -84,23 +114,35 @@ private val GET_TOKEN_RESPONSE_SUCCESS = GetTokenResponseJson.Success(
masterPasswordPolicyOptions = null,
userDecryptionOptions = null,
)
private val ACCOUNT_1 = AccountJson(
profile = AccountJson.Profile(
userId = USER_ID_1,
email = "test@bitwarden.com",
isEmailVerified = true,
name = "Bitwarden Tester",
hasPremium = false,
stamp = null,
organizationId = null,
avatarColorHex = null,
forcePasswordResetReason = null,
kdfType = KdfTypeJson.ARGON2_ID,
kdfIterations = 600000,
kdfMemory = 16,
kdfParallelism = 4,
userDecryptionOptions = null,
private val USER_DECRYPTION_OPTIONS = UserDecryptionOptionsJson(
hasMasterPassword = false,
trustedDeviceUserDecryptionOptions = TrustedDeviceUserDecryptionOptionsJson(
encryptedUserKey = "encryptedUserKey",
encryptedPrivateKey = "encryptedPrivateKey",
hasAdminApproval = true,
hasLoginApprovingDevice = true,
hasManageResetPasswordPermission = true,
),
keyConnectorUserDecryptionOptions = null,
)
private val PROFILE_1 = AccountJson.Profile(
userId = USER_ID_1,
email = "test@bitwarden.com",
isEmailVerified = true,
name = "Bitwarden Tester",
hasPremium = false,
stamp = null,
organizationId = null,
avatarColorHex = null,
forcePasswordResetReason = null,
kdfType = KdfTypeJson.ARGON2_ID,
kdfIterations = 600000,
kdfMemory = 16,
kdfParallelism = 4,
userDecryptionOptions = null,
)
private val ACCOUNT_1 = AccountJson(
profile = PROFILE_1,
settings = AccountJson.Settings(
environmentUrlData = EnvironmentUrlDataJson.DEFAULT_US,
),