mirror of
https://github.com/bitwarden/android.git
synced 2024-11-21 17:05:44 +03:00
[PM-12279] Update SDK reference and use Origin.Android on Fido2Credential (#3975)
This commit is contained in:
parent
10bbab971f
commit
b3e885bcb1
6 changed files with 128 additions and 17 deletions
|
@ -2,6 +2,8 @@ package com.x8bit.bitwarden.data.autofill.fido2.manager
|
|||
|
||||
import androidx.credentials.provider.CallingAppInfo
|
||||
import com.bitwarden.fido.ClientData
|
||||
import com.bitwarden.fido.Origin
|
||||
import com.bitwarden.fido.UnverifiedAssetLink
|
||||
import com.bitwarden.sdk.Fido2CredentialStore
|
||||
import com.bitwarden.vault.CipherView
|
||||
import com.x8bit.bitwarden.data.autofill.fido2.datasource.network.model.DigitalAssetLinkResponseJson
|
||||
|
@ -24,6 +26,7 @@ import com.x8bit.bitwarden.data.vault.datasource.sdk.model.AuthenticateFido2Cred
|
|||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.RegisterFido2CredentialRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.util.toAndroidAttestationResponse
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.util.toAndroidFido2PublicKeyCredential
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.toHostOrPathOrNull
|
||||
import kotlinx.serialization.SerializationException
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
@ -65,11 +68,23 @@ class Fido2CredentialManagerImpl(
|
|||
.packageName,
|
||||
)
|
||||
}
|
||||
val origin = fido2CredentialRequest
|
||||
val assetLinkUrl = fido2CredentialRequest
|
||||
.origin
|
||||
?: getOriginUrlFromAttestationOptionsOrNull(fido2CredentialRequest.requestJson)
|
||||
?: return Fido2RegisterCredentialResult.Error
|
||||
|
||||
val origin = Origin.Android(
|
||||
UnverifiedAssetLink(
|
||||
packageName = fido2CredentialRequest.packageName,
|
||||
sha256CertFingerprint = fido2CredentialRequest
|
||||
.callingAppInfo
|
||||
.getSignatureFingerprintAsHexString()
|
||||
?: return Fido2RegisterCredentialResult.Error,
|
||||
host = assetLinkUrl.toHostOrPathOrNull()
|
||||
?: return Fido2RegisterCredentialResult.Error,
|
||||
assetLinkUrl = assetLinkUrl,
|
||||
),
|
||||
)
|
||||
return vaultSdkSource
|
||||
.registerFido2Credential(
|
||||
request = RegisterFido2CredentialRequest(
|
||||
|
@ -157,7 +172,16 @@ class Fido2CredentialManagerImpl(
|
|||
.authenticateFido2Credential(
|
||||
request = AuthenticateFido2CredentialRequest(
|
||||
userId = userId,
|
||||
origin = origin,
|
||||
origin = Origin.Android(
|
||||
UnverifiedAssetLink(
|
||||
callingAppInfo.packageName,
|
||||
callingAppInfo.getSignatureFingerprintAsHexString()
|
||||
?: return Fido2CredentialAssertionResult.Error,
|
||||
origin.toHostOrPathOrNull()
|
||||
?: return Fido2CredentialAssertionResult.Error,
|
||||
origin,
|
||||
),
|
||||
),
|
||||
requestJson = """{"publicKey": ${request.requestJson}}""",
|
||||
clientData = clientData,
|
||||
selectedCipherView = selectedCipherView,
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package com.x8bit.bitwarden.data.vault.datasource.sdk.model
|
||||
|
||||
import com.bitwarden.fido.ClientData
|
||||
import com.bitwarden.fido.Origin
|
||||
import com.bitwarden.vault.CipherView
|
||||
|
||||
/**
|
||||
* Models a FIDO 2 authentication request to the Bitwarden SDK.
|
||||
*
|
||||
* @param userId User whom the credential is being authenticated for.
|
||||
* @param origin Origin of the Relying Party. This can either be a Relying Party's URL or their
|
||||
* application fingerprint.
|
||||
* @param origin Origin of the Relying Party WebAuthn Request.
|
||||
* @param requestJson Authentication request JSON received from the OS.
|
||||
* @param clientData Metadata containing either privileged application certificate hash or Android
|
||||
* package name of the Relying Party.
|
||||
|
@ -18,7 +18,7 @@ import com.bitwarden.vault.CipherView
|
|||
*/
|
||||
data class AuthenticateFido2CredentialRequest(
|
||||
val userId: String,
|
||||
val origin: String,
|
||||
val origin: Origin,
|
||||
val requestJson: String,
|
||||
val clientData: ClientData,
|
||||
val selectedCipherView: CipherView,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.x8bit.bitwarden.data.vault.datasource.sdk.model
|
||||
|
||||
import com.bitwarden.fido.ClientData
|
||||
import com.bitwarden.fido.Origin
|
||||
import com.bitwarden.vault.CipherView
|
||||
|
||||
/**
|
||||
|
@ -18,7 +19,7 @@ import com.bitwarden.vault.CipherView
|
|||
*/
|
||||
data class RegisterFido2CredentialRequest(
|
||||
val userId: String,
|
||||
val origin: String,
|
||||
val origin: Origin,
|
||||
val requestJson: String,
|
||||
val clientData: ClientData,
|
||||
val selectedCipherView: CipherView,
|
||||
|
|
|
@ -5,7 +5,9 @@ import android.content.pm.SigningInfo
|
|||
import android.util.Base64
|
||||
import androidx.credentials.provider.CallingAppInfo
|
||||
import com.bitwarden.fido.ClientData
|
||||
import com.bitwarden.fido.Origin
|
||||
import com.bitwarden.fido.PublicKeyCredentialAuthenticatorAssertionResponse
|
||||
import com.bitwarden.fido.UnverifiedAssetLink
|
||||
import com.bitwarden.sdk.Fido2CredentialStore
|
||||
import com.x8bit.bitwarden.data.autofill.fido2.datasource.network.model.DigitalAssetLinkResponseJson
|
||||
import com.x8bit.bitwarden.data.autofill.fido2.datasource.network.service.DigitalAssetLinkService
|
||||
|
@ -531,8 +533,58 @@ class Fido2CredentialManagerTest {
|
|||
selectedCipherView = createMockCipherView(number = 1),
|
||||
)
|
||||
|
||||
assertTrue(
|
||||
result is Fido2RegisterCredentialResult.Error,
|
||||
assertEquals(
|
||||
Fido2RegisterCredentialResult.Error,
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `registerFido2Credential should return Error when getSignatureFingerprintAsHexString is null`() =
|
||||
runTest {
|
||||
val mockSigningInfo = mockk<SigningInfo> {
|
||||
every { hasMultipleSigners() } returns true
|
||||
}
|
||||
val mockFido2CredentialRequest = createMockFido2CredentialRequest(
|
||||
number = 1,
|
||||
signingInfo = mockSigningInfo,
|
||||
)
|
||||
|
||||
val result = fido2CredentialManager.registerFido2Credential(
|
||||
userId = "mockUserId",
|
||||
fido2CredentialRequest = mockFido2CredentialRequest,
|
||||
selectedCipherView = createMockCipherView(number = 1),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
Fido2RegisterCredentialResult.Error,
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `registerFido2Credential should return Error when toHostOrPathOrNull is null`() =
|
||||
runTest {
|
||||
val mockSigningInfo = mockk<SigningInfo> {
|
||||
every { apkContentsSigners } returns arrayOf(Signature(DEFAULT_APP_SIGNATURE))
|
||||
every { hasMultipleSigners() } returns false
|
||||
}
|
||||
val mockFido2CredentialRequest = createMockFido2CredentialRequest(
|
||||
number = 1,
|
||||
origin = "illegal empty spaces",
|
||||
signingInfo = mockSigningInfo,
|
||||
)
|
||||
|
||||
val result = fido2CredentialManager.registerFido2Credential(
|
||||
userId = "mockUserId",
|
||||
fido2CredentialRequest = mockFido2CredentialRequest,
|
||||
selectedCipherView = createMockCipherView(number = 1),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
Fido2RegisterCredentialResult.Error,
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -573,8 +625,9 @@ class Fido2CredentialManagerTest {
|
|||
selectedCipherView = createMockCipherView(number = 1),
|
||||
)
|
||||
|
||||
assertTrue(
|
||||
result is Fido2RegisterCredentialResult.Error,
|
||||
assertEquals(
|
||||
Fido2RegisterCredentialResult.Error,
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -709,7 +762,14 @@ class Fido2CredentialManagerTest {
|
|||
assertEquals(
|
||||
AuthenticateFido2CredentialRequest(
|
||||
userId = "activeUserId",
|
||||
origin = mockRequest.origin!!,
|
||||
origin = Origin.Android(
|
||||
UnverifiedAssetLink(
|
||||
packageName = DEFAULT_PACKAGE_NAME,
|
||||
sha256CertFingerprint = DEFAULT_CERT_FINGERPRINT,
|
||||
host = DEFAULT_HOST,
|
||||
assetLinkUrl = mockRequest.origin!!,
|
||||
),
|
||||
),
|
||||
requestJson = """{"publicKey": ${mockRequest.requestJson}}""",
|
||||
clientData = ClientData.DefaultWithExtraData(
|
||||
androidPackageName = "android:apk-key-hash:$DEFAULT_APP_SIGNATURE",
|
||||
|
@ -756,7 +816,14 @@ class Fido2CredentialManagerTest {
|
|||
}
|
||||
|
||||
assertEquals(
|
||||
"https://${mockAssertionOptions.relyingPartyId}",
|
||||
Origin.Android(
|
||||
UnverifiedAssetLink(
|
||||
DEFAULT_PACKAGE_NAME,
|
||||
DEFAULT_CERT_FINGERPRINT,
|
||||
mockAssertionOptions.relyingPartyId!!,
|
||||
"https://${mockAssertionOptions.relyingPartyId}",
|
||||
),
|
||||
),
|
||||
requestCaptureSlot.captured.origin,
|
||||
)
|
||||
}
|
||||
|
@ -942,9 +1009,17 @@ class Fido2CredentialManagerTest {
|
|||
}
|
||||
|
||||
private const val DEFAULT_PACKAGE_NAME = "com.x8bit.bitwarden"
|
||||
private const val DEFAULT_ORIGIN = "bitwarden.com"
|
||||
private const val DEFAULT_APP_SIGNATURE = "0987654321ABCDEF"
|
||||
private const val DEFAULT_CERT_FINGERPRINT = "30:39:38:37:36:35:34:33:32:31:41:42:43:44:45:46"
|
||||
private const val DEFAULT_HOST = "bitwarden.com"
|
||||
private val DEFAULT_ORIGIN = Origin.Android(
|
||||
UnverifiedAssetLink(
|
||||
packageName = DEFAULT_PACKAGE_NAME,
|
||||
sha256CertFingerprint = DEFAULT_CERT_FINGERPRINT,
|
||||
host = DEFAULT_HOST,
|
||||
assetLinkUrl = "bitwarden.com",
|
||||
),
|
||||
)
|
||||
private val DEFAULT_STATEMENT = DigitalAssetLinkResponseJson(
|
||||
relation = listOf(
|
||||
"delegate_permission/common.get_login_creds",
|
||||
|
@ -1029,7 +1104,7 @@ private const val DEFAULT_FIDO2_AUTH_REQUEST_JSON = """
|
|||
"""
|
||||
|
||||
private fun createMockFido2AssertionRequest(
|
||||
mockOrigin: String? = DEFAULT_ORIGIN,
|
||||
mockOrigin: String? = "bitwarden.com",
|
||||
mockClientDataHash: ByteArray? = null,
|
||||
mockSigningInfo: SigningInfo,
|
||||
) = mockk<Fido2CredentialAssertionRequest> {
|
||||
|
|
|
@ -11,8 +11,10 @@ import com.bitwarden.crypto.TrustDeviceResponse
|
|||
import com.bitwarden.exporters.ExportFormat
|
||||
import com.bitwarden.fido.ClientData
|
||||
import com.bitwarden.fido.Fido2CredentialAutofillView
|
||||
import com.bitwarden.fido.Origin
|
||||
import com.bitwarden.fido.PublicKeyCredentialAuthenticatorAssertionResponse
|
||||
import com.bitwarden.fido.PublicKeyCredentialAuthenticatorAttestationResponse
|
||||
import com.bitwarden.fido.UnverifiedAssetLink
|
||||
import com.bitwarden.sdk.BitwardenException
|
||||
import com.bitwarden.sdk.Client
|
||||
import com.bitwarden.sdk.ClientAuth
|
||||
|
@ -1239,9 +1241,18 @@ class VaultSdkSourceTest {
|
|||
}
|
||||
|
||||
private const val DEFAULT_SIGNATURE = "0987654321ABCDEF"
|
||||
|
||||
private val DEFAULT_ORIGIN = Origin.Android(
|
||||
UnverifiedAssetLink(
|
||||
packageName = "com.x8bit.bitwarden",
|
||||
sha256CertFingerprint = "30:39:38:37:36:35:34:33:32:31:41:42:43:44:45:46",
|
||||
host = "bitwarden.com",
|
||||
assetLinkUrl = "www.bitwarden.com",
|
||||
),
|
||||
)
|
||||
private val DEFAULT_FIDO_2_REGISTER_CREDENTIAL_REQUEST = RegisterFido2CredentialRequest(
|
||||
userId = "mockUserId",
|
||||
origin = "www.bitwarden.com",
|
||||
origin = DEFAULT_ORIGIN,
|
||||
requestJson = "requestJson",
|
||||
clientData = ClientData.DefaultWithCustomHash(
|
||||
DEFAULT_SIGNATURE.toByteArray(),
|
||||
|
@ -1251,7 +1262,7 @@ private val DEFAULT_FIDO_2_REGISTER_CREDENTIAL_REQUEST = RegisterFido2Credential
|
|||
)
|
||||
private val DEFAULT_FIDO_2_AUTH_REQUEST = AuthenticateFido2CredentialRequest(
|
||||
userId = "mockUserId",
|
||||
origin = "www.bitwarden.com",
|
||||
origin = DEFAULT_ORIGIN,
|
||||
requestJson = "requestJson",
|
||||
clientData = ClientData.DefaultWithCustomHash(
|
||||
DEFAULT_SIGNATURE.toByteArray(),
|
||||
|
|
|
@ -24,7 +24,7 @@ androidxSplash = "1.1.0-rc01"
|
|||
androidXAppCompat = "1.7.0"
|
||||
androdixAutofill = "1.1.0"
|
||||
androidxWork = "2.9.1"
|
||||
bitwardenSdk = "0.5.0-20240819.160739-177"
|
||||
bitwardenSdk = "1.0.0-20240924.112512-21"
|
||||
crashlytics = "3.0.2"
|
||||
detekt = "1.23.7"
|
||||
firebaseBom = "33.3.0"
|
||||
|
|
Loading…
Reference in a new issue