PM-13803 Check to see if an existing admin request is pending before … (#4271)

This commit is contained in:
Dave Severns 2024-11-11 10:53:11 -05:00 committed by GitHub
parent 1bb85d0fa0
commit 6dd783051f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 219 additions and 42 deletions

View file

@ -7,13 +7,21 @@ import kotlinx.serialization.Serializable
* Container for the user's API tokens. * Container for the user's API tokens.
* *
* @property requestId The ID of the pending Auth Request. * @property requestId The ID of the pending Auth Request.
* @property requestPrivateKey The private of the pending Auth Request. * @property requestPrivateKey The private key of the pending Auth Request.
* @property requestAccessCode The access code of the pending Auth Request.
* @property requestFingerprint The fingerprint of the pending Auth Request.
*/ */
@Serializable @Serializable
data class PendingAuthRequestJson( data class PendingAuthRequestJson(
@SerialName("Id") @SerialName("id")
val requestId: String, val requestId: String,
@SerialName("PrivateKey") @SerialName("privateKey")
val requestPrivateKey: String, val requestPrivateKey: String,
@SerialName("accessCode")
val requestAccessCode: String,
@SerialName("fingerprint")
val requestFingerprint: String,
) )

View file

@ -17,6 +17,7 @@ import com.x8bit.bitwarden.data.auth.manager.model.CreateAuthRequestResult
import com.x8bit.bitwarden.data.auth.manager.util.isSso import com.x8bit.bitwarden.data.auth.manager.util.isSso
import com.x8bit.bitwarden.data.auth.manager.util.toAuthRequestTypeJson import com.x8bit.bitwarden.data.auth.manager.util.toAuthRequestTypeJson
import com.x8bit.bitwarden.data.platform.util.asFailure import com.x8bit.bitwarden.data.platform.util.asFailure
import com.x8bit.bitwarden.data.platform.util.asSuccess
import com.x8bit.bitwarden.data.platform.util.flatMap import com.x8bit.bitwarden.data.platform.util.flatMap
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.currentCoroutineContext
@ -65,7 +66,7 @@ class AuthRequestManagerImpl(
email: String, email: String,
authRequestType: AuthRequestType, authRequestType: AuthRequestType,
): Flow<CreateAuthRequestResult> = flow { ): Flow<CreateAuthRequestResult> = flow {
val initialResult = createNewAuthRequest( val initialResult = createNewAuthRequestIfNecessary(
email = email, email = email,
authRequestType = authRequestType.toAuthRequestTypeJson(), authRequestType = authRequestType.toAuthRequestTypeJson(),
) )
@ -74,7 +75,6 @@ class AuthRequestManagerImpl(
emit(CreateAuthRequestResult.Error) emit(CreateAuthRequestResult.Error)
return@flow return@flow
} }
val authRequestResponse = initialResult.authRequestResponse
var authRequest = initialResult.authRequest var authRequest = initialResult.authRequest
emit(CreateAuthRequestResult.Update(authRequest)) emit(CreateAuthRequestResult.Update(authRequest))
@ -84,7 +84,7 @@ class AuthRequestManagerImpl(
newAuthRequestService newAuthRequestService
.getAuthRequestUpdate( .getAuthRequestUpdate(
requestId = authRequest.id, requestId = authRequest.id,
accessCode = authRequestResponse.accessCode, accessCode = initialResult.accessCode,
isSso = authRequestType.isSso, isSso = authRequestType.isSso,
) )
.map { request -> .map { request ->
@ -112,7 +112,8 @@ class AuthRequestManagerImpl(
emit( emit(
CreateAuthRequestResult.Success( CreateAuthRequestResult.Success(
authRequest = updateAuthRequest, authRequest = updateAuthRequest,
authRequestResponse = authRequestResponse, privateKey = initialResult.privateKey,
accessCode = initialResult.accessCode,
), ),
) )
} }
@ -354,6 +355,52 @@ class AuthRequestManagerImpl(
) )
} }
/**
* Creates a new auth request for the given email and returns a [NewAuthRequestData].
* If the auth request type is [AuthRequestTypeJson.ADMIN_APPROVAL], check for a
* pending auth request and return it if it exists we should return that request.
*/
private suspend fun createNewAuthRequestIfNecessary(
email: String,
authRequestType: AuthRequestTypeJson,
): Result<NewAuthRequestData> {
return if (authRequestType == AuthRequestTypeJson.ADMIN_APPROVAL) {
authDiskSource
.getPendingAuthRequest(requireNotNull(activeUserId))
?.let { pendingAuthRequest ->
authRequestsService
.getAuthRequest(pendingAuthRequest.requestId)
.map {
NewAuthRequestData(
authRequest = AuthRequest(
id = it.id,
publicKey = it.publicKey,
platform = it.platform,
ipAddress = it.ipAddress,
key = it.key,
masterPasswordHash = it.masterPasswordHash,
creationDate = it.creationDate,
responseDate = it.responseDate,
requestApproved = it.requestApproved ?: false,
originUrl = it.originUrl,
fingerprint = pendingAuthRequest.requestFingerprint,
),
privateKey = pendingAuthRequest.requestPrivateKey,
accessCode = pendingAuthRequest.requestAccessCode,
)
.asSuccess()
}
.getOrNull()
}
?: createNewAuthRequest(email = email, authRequestType = authRequestType)
} else {
createNewAuthRequest(
email = email,
authRequestType = authRequestType,
)
}
}
/** /**
* Attempts to create a new auth request for the given email and returns a [NewAuthRequestData] * Attempts to create a new auth request for the given email and returns a [NewAuthRequestData]
* with the [AuthRequest] and [AuthRequestResponse]. * with the [AuthRequest] and [AuthRequestResponse].
@ -381,6 +428,8 @@ class AuthRequestManagerImpl(
pendingAuthRequest = PendingAuthRequestJson( pendingAuthRequest = PendingAuthRequestJson(
requestId = it.id, requestId = it.id,
requestPrivateKey = authRequestResponse.privateKey, requestPrivateKey = authRequestResponse.privateKey,
requestAccessCode = authRequestResponse.accessCode,
requestFingerprint = authRequestResponse.fingerprint,
), ),
) )
} }
@ -400,7 +449,13 @@ class AuthRequestManagerImpl(
fingerprint = authRequestResponse.fingerprint, fingerprint = authRequestResponse.fingerprint,
) )
} }
.map { NewAuthRequestData(it, authRequestResponse) } .map {
NewAuthRequestData(
authRequest = it,
privateKey = authRequestResponse.privateKey,
accessCode = authRequestResponse.accessCode,
)
}
} }
private suspend fun getFingerprintPhrase( private suspend fun getFingerprintPhrase(
@ -420,5 +475,6 @@ class AuthRequestManagerImpl(
*/ */
private data class NewAuthRequestData( private data class NewAuthRequestData(
val authRequest: AuthRequest, val authRequest: AuthRequest,
val authRequestResponse: AuthRequestResponse, val privateKey: String,
val accessCode: String,
) )

View file

@ -1,7 +1,5 @@
package com.x8bit.bitwarden.data.auth.manager.model package com.x8bit.bitwarden.data.auth.manager.model
import com.bitwarden.core.AuthRequestResponse
/** /**
* Models result of creating a new login approval request. * Models result of creating a new login approval request.
*/ */
@ -18,7 +16,8 @@ sealed class CreateAuthRequestResult {
*/ */
data class Success( data class Success(
val authRequest: AuthRequest, val authRequest: AuthRequest,
val authRequestResponse: AuthRequestResponse, val privateKey: String,
val accessCode: String,
) : CreateAuthRequestResult() ) : CreateAuthRequestResult()
/** /**

View file

@ -116,11 +116,11 @@ class LoginWithDeviceViewModel @Inject constructor(
), ),
dialogState = null, dialogState = null,
loginData = LoginWithDeviceState.LoginData( loginData = LoginWithDeviceState.LoginData(
accessCode = result.authRequestResponse.accessCode, accessCode = result.accessCode,
requestId = result.authRequest.id, requestId = result.authRequest.id,
masterPasswordHash = result.authRequest.masterPasswordHash, masterPasswordHash = result.authRequest.masterPasswordHash,
asymmetricalKey = requireNotNull(result.authRequest.key), asymmetricalKey = requireNotNull(result.authRequest.key),
privateKey = result.authRequestResponse.privateKey, privateKey = result.privateKey,
captchaToken = null, captchaToken = null,
), ),
) )

View file

@ -244,6 +244,8 @@ class AuthDiskSourceTest {
val pendingAuthRequestJson = PendingAuthRequestJson( val pendingAuthRequestJson = PendingAuthRequestJson(
requestId = "12345", requestId = "12345",
requestPrivateKey = "67890", requestPrivateKey = "67890",
requestFingerprint = "fingerprint",
requestAccessCode = "accessCode",
) )
authDiskSource.storePendingAuthRequest( authDiskSource.storePendingAuthRequest(
userId = userId, userId = userId,
@ -594,15 +596,22 @@ class AuthDiskSourceTest {
pendingAdminAuthRequestKey, pendingAdminAuthRequestKey,
""" """
{ {
"Id": "12345", "id": "12345",
"PrivateKey": "67890" "privateKey": "67890",
"fingerprint": "fingerprint",
"accessCode": "accessCode"
} }
""", """,
) )
} }
val actual = authDiskSource.getPendingAuthRequest(userId = mockUserId) val actual = authDiskSource.getPendingAuthRequest(userId = mockUserId)
assertEquals( assertEquals(
PendingAuthRequestJson(requestId = "12345", requestPrivateKey = "67890"), PendingAuthRequestJson(
requestId = "12345",
requestPrivateKey = "67890",
requestFingerprint = "fingerprint",
requestAccessCode = "accessCode",
),
actual, actual,
) )
} }
@ -615,6 +624,8 @@ class AuthDiskSourceTest {
val pendingAdminAuthRequest = PendingAuthRequestJson( val pendingAdminAuthRequest = PendingAuthRequestJson(
requestId = "12345", requestId = "12345",
requestPrivateKey = "67890", requestPrivateKey = "67890",
requestFingerprint = "fingerprint",
requestAccessCode = "accessCode",
) )
authDiskSource.storePendingAuthRequest( authDiskSource.storePendingAuthRequest(
userId = mockUserId, userId = mockUserId,
@ -628,8 +639,10 @@ class AuthDiskSourceTest {
json.parseToJsonElement( json.parseToJsonElement(
""" """
{ {
"Id": "12345", "id": "12345",
"PrivateKey": "67890" "privateKey": "67890",
"fingerprint": "fingerprint",
"accessCode": "accessCode"
} }
""" """
.trimIndent(), .trimIndent(),

View file

@ -162,7 +162,8 @@ class AuthRequestManagerTest {
assertEquals( assertEquals(
CreateAuthRequestResult.Success( CreateAuthRequestResult.Success(
authRequest = authRequest.copy(requestApproved = true), authRequest = authRequest.copy(requestApproved = true),
authRequestResponse = authRequestResponse, privateKey = authRequestResponse.privateKey,
accessCode = authRequestResponse.accessCode,
), ),
awaitItem(), awaitItem(),
) )
@ -170,6 +171,87 @@ class AuthRequestManagerTest {
} }
} }
@Suppress("MaxLineLength")
@Test
fun `createAuthRequestWithUpdates with a pending admin request Success and getAuthRequestUpdate with approval should emit Success`() =
runTest {
val email = "email@email.com"
val authRequestResponse = AUTH_REQUEST_RESPONSE
val authRequestResponseJson = AuthRequestsResponseJson.AuthRequest(
id = "1",
publicKey = PUBLIC_KEY,
platform = "Android",
ipAddress = "192.168.0.1",
key = "public",
masterPasswordHash = "verySecureHash",
creationDate = ZonedDateTime.parse("2024-09-13T00:00Z"),
responseDate = null,
requestApproved = false,
originUrl = "www.bitwarden.com",
)
fakeAuthDiskSource.userState = SINGLE_USER_STATE
fakeAuthDiskSource.storePendingAuthRequest(
userId = USER_ID,
pendingAuthRequest = PendingAuthRequestJson(
requestId = authRequestResponseJson.id,
requestPrivateKey = authRequestResponse.privateKey,
requestAccessCode = authRequestResponse.accessCode,
requestFingerprint = authRequestResponse.fingerprint,
),
)
val updatedAuthRequestResponseJson = authRequestResponseJson.copy(
requestApproved = true,
)
val authRequest = AuthRequest(
id = authRequestResponseJson.id,
publicKey = authRequestResponseJson.publicKey,
platform = authRequestResponseJson.platform,
ipAddress = authRequestResponseJson.ipAddress,
key = authRequestResponseJson.key,
masterPasswordHash = authRequestResponseJson.masterPasswordHash,
creationDate = authRequestResponseJson.creationDate,
responseDate = authRequestResponseJson.responseDate,
requestApproved = authRequestResponseJson.requestApproved ?: false,
originUrl = authRequestResponseJson.originUrl,
fingerprint = authRequestResponse.fingerprint,
)
coEvery {
authRequestsService.getAuthRequest(
requestId = authRequest.id,
)
} returns authRequestResponseJson.asSuccess()
coEvery {
newAuthRequestService.getAuthRequestUpdate(
requestId = authRequest.id,
accessCode = authRequestResponse.accessCode,
isSso = true,
)
} returnsMany listOf(
authRequestResponseJson.asSuccess(),
updatedAuthRequestResponseJson.asSuccess(),
)
repository
.createAuthRequestWithUpdates(
email = email,
authRequestType = AuthRequestType.SSO_ADMIN_APPROVAL,
)
.test {
assertEquals(CreateAuthRequestResult.Update(authRequest), awaitItem())
assertEquals(CreateAuthRequestResult.Update(authRequest), awaitItem())
assertEquals(
CreateAuthRequestResult.Success(
authRequest = authRequest.copy(requestApproved = true),
privateKey = authRequestResponse.privateKey,
accessCode = authRequestResponse.accessCode,
),
awaitItem(),
)
awaitComplete()
}
coVerify(exactly = 0) { authSdkSource.getNewAuthRequest(any()) }
}
@Suppress("MaxLineLength") @Suppress("MaxLineLength")
@Test @Test
fun `createAuthRequestWithUpdates with createNewAuthRequest Success and getAuthRequestUpdate with response date and no approval should emit Declined`() = fun `createAuthRequestWithUpdates with createNewAuthRequest Success and getAuthRequestUpdate with response date and no approval should emit Declined`() =
@ -305,6 +387,8 @@ class AuthRequestManagerTest {
pendingAuthRequest = PendingAuthRequestJson( pendingAuthRequest = PendingAuthRequestJson(
requestId = authRequestResponseJson.id, requestId = authRequestResponseJson.id,
requestPrivateKey = authRequestResponse.privateKey, requestPrivateKey = authRequestResponse.privateKey,
requestAccessCode = authRequestResponse.accessCode,
requestFingerprint = authRequestResponse.fingerprint,
), ),
) )
assertEquals(CreateAuthRequestResult.Expired, awaitItem()) assertEquals(CreateAuthRequestResult.Expired, awaitItem())

View file

@ -3566,6 +3566,8 @@ class AuthRepositoryTest {
val pendingAuthRequest = PendingAuthRequestJson( val pendingAuthRequest = PendingAuthRequestJson(
requestId = "requestId", requestId = "requestId",
requestPrivateKey = "requestPrivateKey", requestPrivateKey = "requestPrivateKey",
requestFingerprint = "fingerprint",
requestAccessCode = "accessCode",
) )
val successResponse = GET_TOKEN_RESPONSE_SUCCESS.copy( val successResponse = GET_TOKEN_RESPONSE_SUCCESS.copy(
key = null, key = null,

View file

@ -2,7 +2,6 @@ package com.x8bit.bitwarden.ui.auth.feature.loginwithdevice
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import app.cash.turbine.test import app.cash.turbine.test
import com.bitwarden.core.AuthRequestResponse
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.manager.model.AuthRequest import com.x8bit.bitwarden.data.auth.manager.model.AuthRequest
import com.x8bit.bitwarden.data.auth.manager.model.AuthRequestType import com.x8bit.bitwarden.data.auth.manager.model.AuthRequestType
@ -166,7 +165,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test { viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem()) assertEquals(DEFAULT_STATE, awaitItem())
mutableCreateAuthRequestWithUpdatesFlow.tryEmit( mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE), CreateAuthRequestResult.Success(
authRequest = AUTH_REQUEST,
privateKey = AUTH_REQUEST_PRIVATE_KEY,
accessCode = AUTH_REQUEST_ACCESS_CODE,
),
) )
assertEquals( assertEquals(
DEFAULT_STATE.copy( DEFAULT_STATE.copy(
@ -196,9 +199,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
authRepository.login( authRepository.login(
email = EMAIL, email = EMAIL,
requestId = AUTH_REQUEST.id, requestId = AUTH_REQUEST.id,
accessCode = AUTH_REQUEST_RESPONSE.accessCode, accessCode = AUTH_REQUEST_ACCESS_CODE,
asymmetricalKey = requireNotNull(AUTH_REQUEST.key), asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey, requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
masterPasswordHash = AUTH_REQUEST.masterPasswordHash, masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
captchaToken = null, captchaToken = null,
) )
@ -227,7 +230,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test { viewModel.stateFlow.test {
assertEquals(initialState, awaitItem()) assertEquals(initialState, awaitItem())
mutableCreateAuthRequestWithUpdatesFlow.tryEmit( mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE), CreateAuthRequestResult.Success(
authRequest = AUTH_REQUEST,
privateKey = AUTH_REQUEST_PRIVATE_KEY,
accessCode = AUTH_REQUEST_ACCESS_CODE,
),
) )
assertEquals( assertEquals(
initialState.copy( initialState.copy(
@ -279,7 +286,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel() val viewModel = createViewModel()
viewModel.eventFlow.test { viewModel.eventFlow.test {
mutableCreateAuthRequestWithUpdatesFlow.tryEmit( mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE), CreateAuthRequestResult.Success(
authRequest = AUTH_REQUEST,
privateKey = AUTH_REQUEST_PRIVATE_KEY,
accessCode = AUTH_REQUEST_ACCESS_CODE,
),
) )
assertEquals( assertEquals(
LoginWithDeviceEvent.NavigateToTwoFactorLogin(emailAddress = EMAIL), LoginWithDeviceEvent.NavigateToTwoFactorLogin(emailAddress = EMAIL),
@ -291,9 +302,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
authRepository.login( authRepository.login(
email = EMAIL, email = EMAIL,
requestId = AUTH_REQUEST.id, requestId = AUTH_REQUEST.id,
accessCode = AUTH_REQUEST_RESPONSE.accessCode, accessCode = AUTH_REQUEST_ACCESS_CODE,
asymmetricalKey = requireNotNull(AUTH_REQUEST.key), asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey, requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
masterPasswordHash = AUTH_REQUEST.masterPasswordHash, masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
captchaToken = null, captchaToken = null,
) )
@ -319,7 +330,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test { viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem()) assertEquals(DEFAULT_STATE, awaitItem())
mutableCreateAuthRequestWithUpdatesFlow.tryEmit( mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE), CreateAuthRequestResult.Success(
authRequest = AUTH_REQUEST,
privateKey = AUTH_REQUEST_PRIVATE_KEY,
accessCode = AUTH_REQUEST_ACCESS_CODE,
),
) )
assertEquals( assertEquals(
DEFAULT_STATE.copy( DEFAULT_STATE.copy(
@ -353,9 +368,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
authRepository.login( authRepository.login(
email = EMAIL, email = EMAIL,
requestId = AUTH_REQUEST.id, requestId = AUTH_REQUEST.id,
accessCode = AUTH_REQUEST_RESPONSE.accessCode, accessCode = AUTH_REQUEST_ACCESS_CODE,
asymmetricalKey = requireNotNull(AUTH_REQUEST.key), asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey, requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
masterPasswordHash = AUTH_REQUEST.masterPasswordHash, masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
captchaToken = null, captchaToken = null,
) )
@ -382,7 +397,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test { viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem()) assertEquals(DEFAULT_STATE, awaitItem())
mutableCreateAuthRequestWithUpdatesFlow.tryEmit( mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE), CreateAuthRequestResult.Success(
authRequest = AUTH_REQUEST,
privateKey = AUTH_REQUEST_PRIVATE_KEY,
accessCode = AUTH_REQUEST_ACCESS_CODE,
),
) )
assertEquals( assertEquals(
DEFAULT_STATE.copy( DEFAULT_STATE.copy(
@ -416,9 +435,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
authRepository.login( authRepository.login(
email = EMAIL, email = EMAIL,
requestId = AUTH_REQUEST.id, requestId = AUTH_REQUEST.id,
accessCode = AUTH_REQUEST_RESPONSE.accessCode, accessCode = AUTH_REQUEST_ACCESS_CODE,
asymmetricalKey = requireNotNull(AUTH_REQUEST.key), asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey, requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
masterPasswordHash = AUTH_REQUEST.masterPasswordHash, masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
captchaToken = null, captchaToken = null,
) )
@ -474,9 +493,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
authRepository.login( authRepository.login(
email = EMAIL, email = EMAIL,
requestId = AUTH_REQUEST.id, requestId = AUTH_REQUEST.id,
accessCode = AUTH_REQUEST_RESPONSE.accessCode, accessCode = AUTH_REQUEST_ACCESS_CODE,
asymmetricalKey = requireNotNull(AUTH_REQUEST.key), asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey, requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
masterPasswordHash = AUTH_REQUEST.masterPasswordHash, masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
captchaToken = captchaToken, captchaToken = captchaToken,
) )
@ -603,12 +622,8 @@ private val AUTH_REQUEST = AuthRequest(
fingerprint = FINGERPRINT, fingerprint = FINGERPRINT,
) )
private val AUTH_REQUEST_RESPONSE = AuthRequestResponse( private const val AUTH_REQUEST_ACCESS_CODE = "accessCode"
privateKey = "private_key", private const val AUTH_REQUEST_PRIVATE_KEY = "private_key"
publicKey = "public_key",
accessCode = "accessCode",
fingerprint = "fingerprint",
)
private val DEFAULT_LOGIN_DATA = LoginWithDeviceState.LoginData( private val DEFAULT_LOGIN_DATA = LoginWithDeviceState.LoginData(
accessCode = "accessCode", accessCode = "accessCode",