diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/credentials/model/Fido2AttestationResponse.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/credentials/model/Fido2AttestationResponse.kt index a96af95792..c0b5711531 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/credentials/model/Fido2AttestationResponse.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/credentials/model/Fido2AttestationResponse.kt @@ -20,7 +20,7 @@ data class Fido2AttestationResponse( @SerialName("response") val response: RegistrationResponse, @SerialName("clientExtensionResults") - val clientExtensionResults: ClientExtensionResults?, + val clientExtensionResults: ClientExtensionResults, @SerialName("authenticatorAttachment") val authenticatorAttachment: String?, ) { @@ -50,7 +50,7 @@ data class Fido2AttestationResponse( @Serializable data class ClientExtensionResults( @SerialName("credProps") - val credentialProperties: CredentialProperties, + val credentialProperties: CredentialProperties? = null, ) { /** * Represents properties for newly created credential. diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/util/PublicKeyCredentialAuthenticatorAttestationResponseExtensions.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/util/PublicKeyCredentialAuthenticatorAttestationResponseExtensions.kt index ec6485af7c..edeaefbbda 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/util/PublicKeyCredentialAuthenticatorAttestationResponseExtensions.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/util/PublicKeyCredentialAuthenticatorAttestationResponseExtensions.kt @@ -31,7 +31,7 @@ fun PublicKeyCredentialAuthenticatorAttestationResponse.toAndroidAttestationResp .ClientExtensionResults .CredentialProperties(residentKey = residentKey), ) - }, + } ?: Fido2AttestationResponse.ClientExtensionResults(), authenticatorAttachment = authenticatorAttachment, ) diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/util/PublicKeyCredentialAuthenticatorAttestationResponseExtensionsTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/util/PublicKeyCredentialAuthenticatorAttestationResponseExtensionsTest.kt new file mode 100644 index 0000000000..b092900c5b --- /dev/null +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/util/PublicKeyCredentialAuthenticatorAttestationResponseExtensionsTest.kt @@ -0,0 +1,93 @@ +package com.x8bit.bitwarden.data.vault.datasource.sdk.util + +import android.util.Base64 +import com.bitwarden.fido.AuthenticatorAttestationResponse +import com.bitwarden.fido.ClientExtensionResults +import com.bitwarden.fido.CredPropsResult +import com.bitwarden.fido.PublicKeyCredentialAuthenticatorAttestationResponse +import com.bitwarden.fido.SelectedCredential +import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherView +import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFido2CredentialView +import io.mockk.every +import io.mockk.mockkStatic +import io.mockk.unmockkStatic +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class PublicKeyCredentialAuthenticatorAttestationResponseExtensionsTest { + + @BeforeEach + fun setUp() { + mockkStatic(Base64::class) + every { Base64.encodeToString(any(), any()) } returns "" + } + + @AfterEach + fun tearDown() { + unmockkStatic(Base64::class) + } + + @Test + fun `authenticatorAttachment should be null when SDK value is null`() { + val mockSdkResponse = createMockSdkAttestationResponse(number = 1) + val result = mockSdkResponse.toAndroidAttestationResponse() + assertNull(result.authenticatorAttachment) + } + + @Test + fun `authenticatorAttachment should be populated when SDK value is non-null`() { + val mockSdkResponse = createMockSdkAttestationResponse( + number = 1, + authenticatorAttachment = "mockAuthenticatorAttachment", + ) + val result = mockSdkResponse.toAndroidAttestationResponse() + assertNotNull(result.authenticatorAttachment) + } + + @Test + fun `clientExtensionResults should be populated when SDK value is null`() { + val mockSdkResponse = createMockSdkAttestationResponse(number = 1) + val result = mockSdkResponse.toAndroidAttestationResponse() + assertNotNull(result.clientExtensionResults) + } + + @Test + fun `residentKey should be populated when SDK value is non-null`() { + val mockSdkResponse = createMockSdkAttestationResponse( + number = 1, + credProps = CredPropsResult( + rk = true, + authenticatorDisplayName = null, + ), + ) + val result = mockSdkResponse.toAndroidAttestationResponse() + assert(result.clientExtensionResults.credentialProperties?.residentKey ?: false) + } +} + +private fun createMockSdkAttestationResponse( + number: Int, + authenticatorAttachment: String? = null, + credProps: CredPropsResult? = null, +) = PublicKeyCredentialAuthenticatorAttestationResponse( + id = "mockId-$number", + rawId = byteArrayOf(0), + ty = "mockTy-$number", + authenticatorAttachment = authenticatorAttachment, + clientExtensionResults = ClientExtensionResults(credProps), + response = AuthenticatorAttestationResponse( + clientDataJson = byteArrayOf(0), + authenticatorData = byteArrayOf(0), + publicKey = byteArrayOf(0), + publicKeyAlgorithm = Long.MIN_VALUE, + attestationObject = byteArrayOf(0), + transports = listOf("internal"), + ), + selectedCredential = SelectedCredential( + cipher = createMockCipherView(number = 1), + credential = createMockFido2CredentialView(number = 1), + ), +)