[PM-30899] Store account keys upon SSO user creation (#6384)

This commit is contained in:
Patrick Honkonen
2026-01-23 14:51:25 -05:00
committed by GitHub
parent ee5ed77bc1
commit 2e311b6c4a
7 changed files with 126 additions and 32 deletions

View File

@@ -1,6 +1,7 @@
package com.bitwarden.network.api
import com.bitwarden.network.model.CreateAccountKeysRequest
import com.bitwarden.network.model.CreateAccountKeysResponseJson
import com.bitwarden.network.model.DeleteAccountRequestJson
import com.bitwarden.network.model.NetworkResult
import com.bitwarden.network.model.ResetPasswordRequestJson
@@ -26,7 +27,9 @@ internal interface AuthenticatedAccountsApi {
* Creates the keys for the current account.
*/
@POST("/accounts/keys")
suspend fun createAccountKeys(@Body body: CreateAccountKeysRequest): NetworkResult<Unit>
suspend fun createAccountKeys(
@Body body: CreateAccountKeysRequest,
): NetworkResult<CreateAccountKeysResponseJson>
/**
* Deletes the current account.

View File

@@ -0,0 +1,27 @@
package com.bitwarden.network.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Response object returned when creating account keys.
*
* @property key The user key (nullable).
* @property publicKey The public key for the account.
* @property privateKey The encrypted private key for the account.
* @property accountKeys The account keys containing encryption key pairs and security state.
*/
@Serializable
data class CreateAccountKeysResponseJson(
@SerialName("key")
val key: String?,
@SerialName("publicKey")
val publicKey: String?,
@SerialName("privateKey")
val privateKey: String?,
@SerialName("accountKeys")
val accountKeys: AccountKeysJson?,
)

View File

@@ -1,5 +1,6 @@
package com.bitwarden.network.service
import com.bitwarden.network.model.CreateAccountKeysResponseJson
import com.bitwarden.network.model.DeleteAccountResponseJson
import com.bitwarden.network.model.KeyConnectorKeyRequestJson
import com.bitwarden.network.model.KeyConnectorMasterKeyResponseJson
@@ -26,7 +27,10 @@ interface AccountsService {
/**
* Creates a new account's keys.
*/
suspend fun createAccountKeys(publicKey: String, encryptedPrivateKey: String): Result<Unit>
suspend fun createAccountKeys(
publicKey: String,
encryptedPrivateKey: String,
): Result<CreateAccountKeysResponseJson>
/**
* Make delete account request.

View File

@@ -5,6 +5,7 @@ import com.bitwarden.network.api.AuthenticatedKeyConnectorApi
import com.bitwarden.network.api.UnauthenticatedAccountsApi
import com.bitwarden.network.api.UnauthenticatedKeyConnectorApi
import com.bitwarden.network.model.CreateAccountKeysRequest
import com.bitwarden.network.model.CreateAccountKeysResponseJson
import com.bitwarden.network.model.DeleteAccountRequestJson
import com.bitwarden.network.model.DeleteAccountResponseJson
import com.bitwarden.network.model.KeyConnectorKeyRequestJson
@@ -50,7 +51,7 @@ internal class AccountsServiceImpl(
override suspend fun createAccountKeys(
publicKey: String,
encryptedPrivateKey: String,
): Result<Unit> =
): Result<CreateAccountKeysResponseJson> =
authenticatedAccountsApi
.createAccountKeys(
body = CreateAccountKeysRequest(

View File

@@ -53,11 +53,10 @@ class AccountsServiceTest : BaseServiceTest() {
}
@Test
fun `createAccountKeys with empty response is success`() = runTest {
fun `createAccountKeys success response should return Success`() = runTest {
val publicKey = "publicKey"
val encryptedPrivateKey = "encryptedPrivateKey"
val json = ""
val response = MockResponse().setBody(json)
val response = MockResponse().setBody(CREATE_ACCOUNT_KEYS_REQUEST_RESPONSE)
server.enqueue(response)
val result = service.createAccountKeys(
@@ -368,3 +367,22 @@ private val UPDATE_KDF_REQUEST = UpdateKdfJsonRequest(
salt = "mockSalt",
),
)
private val CREATE_ACCOUNT_KEYS_REQUEST_RESPONSE = """
{
"key": null,
"publicKey": "mockPublicKey-1",
"privateKey": "mockPrivateKey-1",
"accountKeys": {
"signatureKeyPair": null,
"publicKeyEncryptionKeyPair": {
"wrappedPrivateKey": "mockWrappedPrivateKey-1",
"publicKey": "mockPublicKey-1",
"signedPublicKey": null,
"object": "publicKeyEncryptionKeyPair"
},
"securityState": null,
"object": "privateKeys"
},
"object": "keys"
}
""".trimIndent()