mirror of
https://github.com/bitwarden/android.git
synced 2025-03-16 11:18:45 +03:00
BIT-2046 Define FIDO2 credential network models (#1137)
This commit is contained in:
parent
77a40aeb2f
commit
143a46165c
14 changed files with 235 additions and 6 deletions
|
@ -91,5 +91,8 @@ object PlatformNetworkModule {
|
|||
serializersModule = SerializersModule {
|
||||
contextual(ZonedDateTimeSerializer())
|
||||
}
|
||||
|
||||
// Respect model default property values.
|
||||
coerceInputValues = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,10 @@ import kotlinx.serialization.Serializable
|
|||
import kotlinx.serialization.json.JsonObject
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
private const val DEFAULT_FIDO_2_KEY_TYPE = "public-key"
|
||||
private const val DEFAULT_FIDO_2_KEY_ALGORITHM = "ECDSA"
|
||||
private const val DEFAULT_FIDO_2_KEY_CURVE = "P-256"
|
||||
|
||||
/**
|
||||
* Represents the response model for vault data fetched from the server.
|
||||
*
|
||||
|
@ -731,6 +735,9 @@ data class SyncResponseJson(
|
|||
|
||||
@SerialName("username")
|
||||
val username: String?,
|
||||
|
||||
@SerialName("fido2Credentials")
|
||||
val fido2Credentials: List<Fido2Credential>?,
|
||||
) {
|
||||
/**
|
||||
* Represents a URI in the vault response.
|
||||
|
@ -774,6 +781,66 @@ data class SyncResponseJson(
|
|||
@SerialName("type")
|
||||
val type: SecureNoteTypeJson,
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents a FIDO2 credential object in the vault response.
|
||||
*
|
||||
* @property credentialId The unique identifier of the FIDO2 credential.
|
||||
* @property keyType The type of public key of the FIDO2 credential.
|
||||
* @property keyAlgorithm The public Key algorithm of the credential.
|
||||
* @property keyValue The public key of the credential.
|
||||
* @property rpId The relying party (RP) identity.
|
||||
* @property rpName The optional name of the relying party (RP).
|
||||
* @property userHandle The optional unique identifier used to identify an account.
|
||||
* @property userName The conditional, formal name of the user associated to the credential.
|
||||
* @property userDisplayName The optional display name of the user associated to the
|
||||
* credential.
|
||||
* @property counter The signature counter for the credential.
|
||||
* @property discoverable Whether the FIDO2 credential is discoverable or non-discoverable.
|
||||
* @property creationDate The creation date and time of the credential.
|
||||
*/
|
||||
@Serializable
|
||||
data class Fido2Credential(
|
||||
@SerialName("credentialId")
|
||||
val credentialId: String,
|
||||
|
||||
@SerialName("keyType")
|
||||
val keyType: String = DEFAULT_FIDO_2_KEY_TYPE,
|
||||
|
||||
@SerialName("keyAlgorithm")
|
||||
val keyAlgorithm: String = DEFAULT_FIDO_2_KEY_ALGORITHM,
|
||||
|
||||
@SerialName("keyCurve")
|
||||
val keyCurve: String = DEFAULT_FIDO_2_KEY_CURVE,
|
||||
|
||||
@SerialName("keyValue")
|
||||
val keyValue: String,
|
||||
|
||||
@SerialName("rpId")
|
||||
val rpId: String,
|
||||
|
||||
@SerialName("rpName")
|
||||
val rpName: String?,
|
||||
|
||||
@SerialName("userHandle")
|
||||
val userHandle: String?,
|
||||
|
||||
@SerialName("userName")
|
||||
val userName: String?,
|
||||
|
||||
@SerialName("userDisplayName")
|
||||
val userDisplayName: String?,
|
||||
|
||||
@SerialName("counter")
|
||||
val counter: String,
|
||||
|
||||
@SerialName("discoverable")
|
||||
val discoverable: String,
|
||||
|
||||
@SerialName("creationDate")
|
||||
@Contextual
|
||||
val creationDate: ZonedDateTime,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.bitwarden.core.Cipher
|
|||
import com.bitwarden.core.CipherRepromptType
|
||||
import com.bitwarden.core.CipherType
|
||||
import com.bitwarden.core.CipherView
|
||||
import com.bitwarden.core.Fido2Credential
|
||||
import com.bitwarden.core.Field
|
||||
import com.bitwarden.core.FieldType
|
||||
import com.bitwarden.core.Identity
|
||||
|
@ -232,8 +233,28 @@ private fun Login.toEncryptedNetworkLogin(): SyncResponseJson.Cipher.Login =
|
|||
// uri needs to be null to avoid duplicating the first url entry for a login item.
|
||||
uri = null,
|
||||
username = username,
|
||||
fido2Credentials = fido2Credentials?.toNetworkFido2Credentials(),
|
||||
)
|
||||
|
||||
private fun List<Fido2Credential>.toNetworkFido2Credentials() =
|
||||
this.map { it.toNetworkFido2Credential() }
|
||||
|
||||
private fun Fido2Credential.toNetworkFido2Credential() = SyncResponseJson.Cipher.Fido2Credential(
|
||||
credentialId = credentialId,
|
||||
keyType = keyType,
|
||||
keyAlgorithm = keyAlgorithm,
|
||||
keyCurve = keyCurve,
|
||||
keyValue = keyValue,
|
||||
rpId = rpId,
|
||||
rpName = rpName,
|
||||
userHandle = userHandle,
|
||||
userName = userName,
|
||||
userDisplayName = userDisplayName,
|
||||
counter = counter,
|
||||
discoverable = discoverable,
|
||||
creationDate = ZonedDateTime.ofInstant(creationDate, ZoneOffset.UTC),
|
||||
)
|
||||
|
||||
/**
|
||||
* Converts a list of Bitwarden SDK [PasswordHistory] objects to a corresponding
|
||||
* list of [SyncResponseJson.Cipher.PasswordHistory] objects.
|
||||
|
@ -325,8 +346,28 @@ fun SyncResponseJson.Cipher.Login.toSdkLogin(): Login =
|
|||
uris = uris?.toSdkLoginUriList(),
|
||||
totp = totp,
|
||||
autofillOnPageLoad = shouldAutofillOnPageLoad,
|
||||
fido2Credentials = fido2Credentials?.toSdkFido2Credentials(),
|
||||
)
|
||||
|
||||
private fun List<SyncResponseJson.Cipher.Fido2Credential>.toSdkFido2Credentials() =
|
||||
this.map { it.toSdkFido2Credential() }
|
||||
|
||||
private fun SyncResponseJson.Cipher.Fido2Credential.toSdkFido2Credential() = Fido2Credential(
|
||||
credentialId = credentialId,
|
||||
keyType = keyType,
|
||||
keyAlgorithm = keyAlgorithm,
|
||||
keyCurve = keyCurve,
|
||||
keyValue = keyValue,
|
||||
rpId = rpId,
|
||||
rpName = rpName,
|
||||
userHandle = userHandle,
|
||||
userName = userName,
|
||||
userDisplayName = userDisplayName,
|
||||
counter = counter,
|
||||
discoverable = discoverable,
|
||||
creationDate = creationDate.toInstant(),
|
||||
)
|
||||
|
||||
/**
|
||||
* Transforms a [SyncResponseJson.Cipher.Identity] into the corresponding Bitwarden SDK [Identity].
|
||||
*/
|
||||
|
|
|
@ -147,6 +147,7 @@ private fun VaultAddEditState.ViewState.Content.ItemType.toLoginView(
|
|||
uris = it.uriList.toLoginUriView(),
|
||||
totp = it.totp,
|
||||
autofillOnPageLoad = common.originalCipher?.login?.autofillOnPageLoad,
|
||||
fido2Credentials = common.originalCipher?.login?.fido2Credentials,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -337,7 +337,24 @@ private const val CIPHER_JSON = """
|
|||
"passwordRevisionDate": "2023-10-27T12:00:00.000Z",
|
||||
"autofillOnPageLoad": false,
|
||||
"uri": "mockUri-1",
|
||||
"username": "mockUsername-1"
|
||||
"username": "mockUsername-1",
|
||||
"fido2Credentials": [
|
||||
{
|
||||
"credentialId": "mockCredentialId-1",
|
||||
"keyType": "mockKeyType-1",
|
||||
"keyAlgorithm": "mockKeyAlgorithm-1",
|
||||
"keyCurve": "mockKeyCurve-1",
|
||||
"keyValue": "mockKeyValue-1",
|
||||
"rpId": "mockRpId-1",
|
||||
"rpName": "mockRpName-1",
|
||||
"userHandle": "mockUserHandle-1",
|
||||
"userName": "mockUserName-1",
|
||||
"userDisplayName": "mockUserDisplayName-1",
|
||||
"counter": "mockCounter-1",
|
||||
"discoverable": "mockDiscoverable-1",
|
||||
"creationDate": "2024-03-12T20:20:16.456Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
"creationDate": "2023-10-27T12:00:00.000Z",
|
||||
"secureNote": {
|
||||
|
|
|
@ -120,11 +120,28 @@ fun createMockLogin(number: Int, hasNullUri: Boolean = false): SyncResponseJson.
|
|||
password = "mockPassword-$number",
|
||||
passwordRevisionDate = ZonedDateTime.parse("2023-10-27T12:00:00Z"),
|
||||
shouldAutofillOnPageLoad = false,
|
||||
uri = if (hasNullUri) { null } else "mockUri-$number",
|
||||
uri = if (hasNullUri) null else "mockUri-$number",
|
||||
uris = listOf(createMockUri(number = number)),
|
||||
totp = "mockTotp-$number",
|
||||
fido2Credentials = listOf(createMockFido2Credential(number)),
|
||||
)
|
||||
|
||||
fun createMockFido2Credential(number: Int) = SyncResponseJson.Cipher.Fido2Credential(
|
||||
credentialId = "mockCredentialId-$number",
|
||||
keyType = "mockKeyType-$number",
|
||||
keyAlgorithm = "mockKeyAlgorithm-$number",
|
||||
keyCurve = "mockKeyCurve-$number",
|
||||
keyValue = "mockKeyValue-$number",
|
||||
rpId = "mockRpId-$number",
|
||||
rpName = "mockRpName-$number",
|
||||
userHandle = "mockUserHandle-$number",
|
||||
userName = "mockUserName-$number",
|
||||
userDisplayName = "mockUserDisplayName-$number",
|
||||
counter = "mockCounter-$number",
|
||||
discoverable = "mockDiscoverable-$number",
|
||||
creationDate = ZonedDateTime.parse("2024-03-12T20:20:16.456Z"),
|
||||
)
|
||||
|
||||
/**
|
||||
* Create a mock [SyncResponseJson.Cipher.Login.Uri] with a given [number].
|
||||
*/
|
||||
|
|
|
@ -314,7 +314,24 @@ private const val CREATE_ATTACHMENT_SUCCESS_JSON = """
|
|||
"passwordRevisionDate": "2023-10-27T12:00:00.00Z",
|
||||
"autofillOnPageLoad": false,
|
||||
"uri": "mockUri-1",
|
||||
"username": "mockUsername-1"
|
||||
"username": "mockUsername-1",
|
||||
"fido2Credentials": [
|
||||
{
|
||||
"credentialId": "mockCredentialId-1",
|
||||
"keyType": "mockKeyType-1",
|
||||
"keyAlgorithm": "mockKeyAlgorithm-1",
|
||||
"keyCurve": "mockKeyCurve-1",
|
||||
"keyValue": "mockKeyValue-1",
|
||||
"rpId": "mockRpId-1",
|
||||
"rpName": "mockRpName-1",
|
||||
"userHandle": "mockUserHandle-1",
|
||||
"userName": "mockUserName-1",
|
||||
"userDisplayName": "mockUserDisplayName-1",
|
||||
"counter": "mockCounter-1",
|
||||
"discoverable": "mockDiscoverable-1",
|
||||
"creationDate": "2024-03-12T20:20:16.456Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
"creationDate": "2023-10-27T12:00:00.00Z",
|
||||
"secureNote": {
|
||||
|
@ -407,7 +424,24 @@ private const val CREATE_UPDATE_CIPHER_SUCCESS_JSON = """
|
|||
"passwordRevisionDate": "2023-10-27T12:00:00.00Z",
|
||||
"autofillOnPageLoad": false,
|
||||
"uri": "mockUri-1",
|
||||
"username": "mockUsername-1"
|
||||
"username": "mockUsername-1",
|
||||
"fido2Credentials": [
|
||||
{
|
||||
"credentialId": "mockCredentialId-1",
|
||||
"keyType": "mockKeyType-1",
|
||||
"keyAlgorithm": "mockKeyAlgorithm-1",
|
||||
"keyCurve": "mockKeyCurve-1",
|
||||
"keyValue": "mockKeyValue-1",
|
||||
"rpId": "mockRpId-1",
|
||||
"rpName": "mockRpName-1",
|
||||
"userHandle": "mockUserHandle-1",
|
||||
"userName": "mockUserName-1",
|
||||
"userDisplayName": "mockUserDisplayName-1",
|
||||
"counter": "mockCounter-1",
|
||||
"discoverable": "mockDiscoverable-1",
|
||||
"creationDate": "2024-03-12T20:20:16.456Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
"creationDate": "2023-10-27T12:00:00.00Z",
|
||||
"secureNote": {
|
||||
|
|
|
@ -230,7 +230,24 @@ private const val SYNC_SUCCESS_JSON = """
|
|||
"passwordRevisionDate": "2023-10-27T12:00:00.00Z",
|
||||
"autofillOnPageLoad": false,
|
||||
"uri": "mockUri-1",
|
||||
"username": "mockUsername-1"
|
||||
"username": "mockUsername-1",
|
||||
"fido2Credentials": [
|
||||
{
|
||||
"credentialId": "mockCredentialId-1",
|
||||
"keyType": "mockKeyType-1",
|
||||
"keyAlgorithm": "mockKeyAlgorithm-1",
|
||||
"keyCurve": "mockKeyCurve-1",
|
||||
"keyValue": "mockKeyValue-1",
|
||||
"rpId": "mockRpId-1",
|
||||
"rpName": "mockRpName-1",
|
||||
"userHandle": "mockUserHandle-1",
|
||||
"userName": "mockUserName-1",
|
||||
"userDisplayName": "mockUserDisplayName-1",
|
||||
"counter": "mockCounter-1",
|
||||
"discoverable": "mockDiscoverable-1",
|
||||
"creationDate": "2024-03-12T20:20:16.456Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
"creationDate": "2023-10-27T12:00:00.00Z",
|
||||
"secureNote": {
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.bitwarden.core.CardView
|
|||
import com.bitwarden.core.CipherRepromptType
|
||||
import com.bitwarden.core.CipherType
|
||||
import com.bitwarden.core.CipherView
|
||||
import com.bitwarden.core.Fido2Credential
|
||||
import com.bitwarden.core.FieldType
|
||||
import com.bitwarden.core.FieldView
|
||||
import com.bitwarden.core.IdentityView
|
||||
|
@ -89,6 +90,29 @@ fun createMockLoginView(
|
|||
autofillOnPageLoad = false,
|
||||
uris = listOf(createMockUriView(number = number)),
|
||||
totp = totp,
|
||||
fido2Credentials = createMockSdkFido2CredentialList(number),
|
||||
)
|
||||
|
||||
fun createMockSdkFido2CredentialList(number: Int) =
|
||||
listOf(createMockSdkFido2CredentialView(number))
|
||||
|
||||
fun createMockSdkFido2CredentialView(number: Int) =
|
||||
Fido2Credential(
|
||||
credentialId = "mockCredentialId-$number",
|
||||
keyType = "mockKeyType-$number",
|
||||
keyAlgorithm = "mockKeyAlgorithm-$number",
|
||||
keyCurve = "mockKeyCurve-$number",
|
||||
keyValue = "mockKeyValue-$number",
|
||||
rpId = "mockRpId-$number",
|
||||
userHandle = "mockUserHandle-$number",
|
||||
userName = "mockUserName-$number",
|
||||
counter = "mockCounter-$number",
|
||||
rpName = "mockRpName-$number",
|
||||
userDisplayName = "mockUserDisplayName-$number",
|
||||
discoverable = "mockDiscoverable-$number",
|
||||
creationDate = ZonedDateTime
|
||||
.parse("2024-03-12T20:20:16.456Z")
|
||||
.toInstant(),
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -147,6 +147,7 @@ fun createMockSdkLogin(number: Int): Login =
|
|||
autofillOnPageLoad = false,
|
||||
uris = listOf(createMockSdkUri(number = number)),
|
||||
totp = "mockTotp-$number",
|
||||
fido2Credentials = createMockSdkFido2CredentialList(number),
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
|||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCollectionView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFolderView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkFido2CredentialList
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import com.x8bit.bitwarden.ui.platform.manager.resource.ResourceManager
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
|
||||
|
@ -529,6 +530,7 @@ private val DEFAULT_LOGIN_CIPHER_VIEW: CipherView = DEFAULT_BASE_CIPHER_VIEW.cop
|
|||
),
|
||||
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
|
||||
autofillOnPageLoad = false,
|
||||
fido2Credentials = createMockSdkFido2CredentialList(number = 1),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.bitwarden.core.IdentityView
|
|||
import com.bitwarden.core.LoginUriView
|
||||
import com.bitwarden.core.LoginView
|
||||
import com.bitwarden.core.PasswordHistoryView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkFido2CredentialList
|
||||
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemState
|
||||
import com.x8bit.bitwarden.ui.vault.feature.item.model.TotpCodeItemData
|
||||
import com.x8bit.bitwarden.ui.vault.model.VaultLinkedFieldType
|
||||
|
@ -42,6 +43,7 @@ fun createLoginView(isEmpty: Boolean): LoginView =
|
|||
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example"
|
||||
.takeUnless { isEmpty },
|
||||
autofillOnPageLoad = false,
|
||||
fido2Credentials = createMockSdkFido2CredentialList(number = 1),
|
||||
)
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
|
|
|
@ -84,6 +84,7 @@ class VaultAddItemStateExtensionsTest {
|
|||
),
|
||||
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
|
||||
autofillOnPageLoad = null,
|
||||
fido2Credentials = null,
|
||||
),
|
||||
identity = null,
|
||||
card = null,
|
||||
|
@ -162,6 +163,7 @@ class VaultAddItemStateExtensionsTest {
|
|||
),
|
||||
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
|
||||
autofillOnPageLoad = false,
|
||||
fido2Credentials = null,
|
||||
),
|
||||
favorite = true,
|
||||
reprompt = CipherRepromptType.NONE,
|
||||
|
@ -741,6 +743,7 @@ private val DEFAULT_LOGIN_CIPHER_VIEW: CipherView = DEFAULT_BASE_CIPHER_VIEW.cop
|
|||
),
|
||||
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
|
||||
autofillOnPageLoad = false,
|
||||
fido2Credentials = null,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ androidxSplash = "1.1.0-alpha02"
|
|||
androidXAppCompat = "1.6.1"
|
||||
androdixAutofill = "1.1.0"
|
||||
androidxWork = "2.9.0"
|
||||
bitwardenSdk = "0.4.0-20240306.185653-166"
|
||||
bitwardenSdk = "0.4.0-20240314.115913-173"
|
||||
crashlytics = "2.9.9"
|
||||
detekt = "1.23.5"
|
||||
firebaseBom = "32.7.3"
|
||||
|
|
Loading…
Add table
Reference in a new issue