Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.datasource.sdk

import com.bitwarden.auth.JitMasterPasswordRegistrationResponse
import com.bitwarden.auth.KeyConnectorRegistrationResult
import com.bitwarden.auth.PasswordPreloginResponse
import com.bitwarden.auth.TdeRegistrationResponse
import com.bitwarden.auth.UserMasterPasswordRegistrationResponse
import com.bitwarden.core.AuthRequestResponse
Expand All @@ -21,6 +22,11 @@ import com.x8bit.bitwarden.data.auth.datasource.sdk.model.PasswordStrength
*/
@Suppress("TooManyFunctions")
interface AuthSdkSource {
/**
* Performs the pre-login request for the given email address.
*/
suspend fun preLogin(email: String): Result<PasswordPreloginResponse>

/**
* Enrolls the user to master password unlock.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.sdk
import com.bitwarden.auth.JitMasterPasswordRegistrationRequest
import com.bitwarden.auth.JitMasterPasswordRegistrationResponse
import com.bitwarden.auth.KeyConnectorRegistrationResult
import com.bitwarden.auth.PasswordPreloginResponse
import com.bitwarden.auth.TdeRegistrationRequest
import com.bitwarden.auth.TdeRegistrationResponse
import com.bitwarden.auth.UserMasterPasswordRegistrationRequest
Expand Down Expand Up @@ -38,6 +39,14 @@ class AuthSdkSourceImpl(
) : BaseSdkSource(sdkClientManager = sdkClientManager),
AuthSdkSource {

override suspend fun preLogin(
email: String,
): Result<PasswordPreloginResponse> = runCatchingWithLogs {
withContext(context = dispatcherManager.io) {
useClient { auth().login().getPasswordPrelogin(email = email) }
}
}

override suspend fun postKeysForJitPasswordRegistration(
userId: String,
organizationId: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.x8bit.bitwarden.data.auth.repository

import com.bitwarden.auth.PasswordPreloginResponse
import com.bitwarden.core.AuthRequestMethod
import com.bitwarden.core.InitUserCryptoMethod
import com.bitwarden.core.MasterPasswordUnlockData
Expand Down Expand Up @@ -529,13 +530,18 @@ internal class AuthRepositoryImpl(
override suspend fun login(
email: String,
password: String,
): LoginResult = identityService
.preLogin(email = email)
): LoginResult = if (featureFlagManager.getFeatureFlag(key = FlagKey.SdkPreLogin)) {
authSdkSource.preLogin(email = email)
} else {
identityService
.preLogin(email = email)
.map { PasswordPreloginResponse(salt = email, kdf = it.kdfParams.toSdkParams()) }
}
Comment thread
david-livefront marked this conversation as resolved.
.flatMap {
authSdkSource.hashPassword(
salt = email,
salt = it.salt,
password = password,
kdf = it.kdfParams.toSdkParams(),
kdf = it.kdf,
purpose = HashPurpose.SERVER_AUTHORIZATION,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ class FakeAuthDiskSource : AuthDiskSource {
/**
* Assert that the given [userState] matches the currently tracked value.
*/
fun assertUserState(userState: UserStateJson) {
fun assertUserState(userState: UserStateJson?) {
assertEquals(userState, this.userState)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.sdk
import com.bitwarden.auth.JitMasterPasswordRegistrationRequest
import com.bitwarden.auth.JitMasterPasswordRegistrationResponse
import com.bitwarden.auth.KeyConnectorRegistrationResult
import com.bitwarden.auth.PasswordPreloginResponse
import com.bitwarden.auth.TdeRegistrationRequest
import com.bitwarden.auth.TdeRegistrationResponse
import com.bitwarden.auth.UserMasterPasswordRegistrationRequest
Expand All @@ -14,6 +15,7 @@ import com.bitwarden.core.MasterPasswordPolicyOptions
import com.bitwarden.core.RegisterKeyResponse
import com.bitwarden.core.RegisterTdeKeyResponse
import com.bitwarden.core.data.manager.dispatcher.FakeDispatcherManager
import com.bitwarden.core.data.util.asFailure
import com.bitwarden.core.data.util.asSuccess
import com.bitwarden.crypto.HashPurpose
import com.bitwarden.crypto.Kdf
Expand All @@ -22,6 +24,7 @@ import com.bitwarden.policies.PolicyType
import com.bitwarden.policies.PolicyView
import com.bitwarden.sdk.AuthClient
import com.bitwarden.sdk.Client
import com.bitwarden.sdk.LoginClient
import com.bitwarden.sdk.PlatformClient
import com.bitwarden.sdk.PoliciesClient
import com.bitwarden.sdk.RegistrationClient
Expand All @@ -40,12 +43,14 @@ import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class AuthSdkSourceTest {
private val clientLogin = mockk<LoginClient>()
private val clientRegistration = mockk<RegistrationClient>()
private val clientAuth = mockk<AuthClient> {
every { registration() } returns clientRegistration
every { login() } returns clientLogin
}
private val clientPlatform = mockk<PlatformClient> {
coEvery { loadFlags(any()) } just runs
coEvery { loadFlags(flags = any()) } just runs
}
private val clientPolicies = mockk<PoliciesClient>()
private val client = mockk<Client> {
Expand All @@ -63,6 +68,38 @@ class AuthSdkSourceTest {
sdkClientManager = sdkClientManager,
)

@Test
fun `preLogin should call SDK and return a Result with correct data`() = runBlocking {
val email = "email@example.com"
val expectedResult = mockk<PasswordPreloginResponse>()
val slot = slot<suspend Client.() -> PasswordPreloginResponse>()
coEvery {
sdkClientManager.singleUseClient(block = capture(slot))
} coAnswers { slot.captured(client) }
coEvery { clientLogin.getPasswordPrelogin(email = email) } returns expectedResult

val result = authSkdSource.preLogin(email = email)

assertEquals(expectedResult.asSuccess(), result)
coVerify(exactly = 1) { clientLogin.getPasswordPrelogin(email = email) }
}

@Test
fun `preLogin should return a failure when the SDK throws`() = runBlocking {
val email = "email@example.com"
val error = RuntimeException("Fail")
val slot = slot<suspend Client.() -> PasswordPreloginResponse>()
coEvery {
sdkClientManager.singleUseClient(block = capture(slot))
} coAnswers { slot.captured(client) }
coEvery { clientLogin.getPasswordPrelogin(email = email) } throws error

val result = authSkdSource.preLogin(email = email)

assertEquals(error.asFailure(), result)
coVerify(exactly = 1) { clientLogin.getPasswordPrelogin(email = email) }
}

@Suppress("MaxLineLength")
@Test
fun `postKeysForJitPasswordRegistration should call SDK and return a Result with correct data`() =
Expand Down
Loading
Loading