mirror of
https://github.com/bitwarden/android.git
synced 2025-12-12 00:08:00 -06:00
[PM-24258] Building a specific Fido2AttestationResponse to work with Binance (#5986)
This commit is contained in:
parent
2d2b740ae1
commit
a7bbb81b31
@ -323,6 +323,7 @@ class BitwardenCredentialManagerImpl(
|
|||||||
createPublicKeyCredentialRequest = createPublicKeyCredentialRequest,
|
createPublicKeyCredentialRequest = createPublicKeyCredentialRequest,
|
||||||
selectedCipherView = selectedCipherView,
|
selectedCipherView = selectedCipherView,
|
||||||
clientData = clientData,
|
clientData = clientData,
|
||||||
|
callingPackageName = callingAppInfo.packageName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +348,7 @@ class BitwardenCredentialManagerImpl(
|
|||||||
createPublicKeyCredentialRequest = createPublicKeyCredentialRequest,
|
createPublicKeyCredentialRequest = createPublicKeyCredentialRequest,
|
||||||
selectedCipherView = selectedCipherView,
|
selectedCipherView = selectedCipherView,
|
||||||
clientData = clientData,
|
clientData = clientData,
|
||||||
|
callingPackageName = callingAppInfo.packageName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,6 +358,7 @@ class BitwardenCredentialManagerImpl(
|
|||||||
createPublicKeyCredentialRequest: CreatePublicKeyCredentialRequest,
|
createPublicKeyCredentialRequest: CreatePublicKeyCredentialRequest,
|
||||||
selectedCipherView: CipherView,
|
selectedCipherView: CipherView,
|
||||||
clientData: ClientData,
|
clientData: ClientData,
|
||||||
|
callingPackageName: String,
|
||||||
): Fido2RegisterCredentialResult = vaultSdkSource
|
): Fido2RegisterCredentialResult = vaultSdkSource
|
||||||
.registerFido2Credential(
|
.registerFido2Credential(
|
||||||
request = RegisterFido2CredentialRequest(
|
request = RegisterFido2CredentialRequest(
|
||||||
@ -370,7 +373,9 @@ class BitwardenCredentialManagerImpl(
|
|||||||
),
|
),
|
||||||
fido2CredentialStore = this,
|
fido2CredentialStore = this,
|
||||||
)
|
)
|
||||||
.map { it.toAndroidAttestationResponse() }
|
.map {
|
||||||
|
it.toAndroidAttestationResponse(callingPackageName = callingPackageName)
|
||||||
|
}
|
||||||
.mapCatching { json.encodeToString(it) }
|
.mapCatching { json.encodeToString(it) }
|
||||||
.fold(
|
.fold(
|
||||||
onSuccess = { Fido2RegisterCredentialResult.Success(it) },
|
onSuccess = { Fido2RegisterCredentialResult.Success(it) },
|
||||||
|
|||||||
@ -4,24 +4,33 @@ import android.util.Base64
|
|||||||
import com.bitwarden.fido.PublicKeyCredentialAuthenticatorAttestationResponse
|
import com.bitwarden.fido.PublicKeyCredentialAuthenticatorAttestationResponse
|
||||||
import com.x8bit.bitwarden.data.credentials.model.Fido2AttestationResponse
|
import com.x8bit.bitwarden.data.credentials.model.Fido2AttestationResponse
|
||||||
|
|
||||||
|
private const val BINANCE_PACKAGE_NAME = "com.binance.dev"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the SDK attestation response to a [Fido2AttestationResponse] that can be serialized into
|
* Converts the SDK attestation response to a [Fido2AttestationResponse] that can be serialized into
|
||||||
* the expected system JSON.
|
* the expected system JSON.
|
||||||
*/
|
*/
|
||||||
@Suppress("MaxLineLength")
|
fun PublicKeyCredentialAuthenticatorAttestationResponse.toAndroidAttestationResponse(
|
||||||
fun PublicKeyCredentialAuthenticatorAttestationResponse.toAndroidAttestationResponse(): Fido2AttestationResponse =
|
callingPackageName: String?,
|
||||||
Fido2AttestationResponse(
|
): Fido2AttestationResponse {
|
||||||
id = id,
|
val registrationResponse = Fido2AttestationResponse.RegistrationResponse(
|
||||||
type = ty,
|
|
||||||
rawId = rawId.base64EncodeForFido2Response(),
|
|
||||||
response = Fido2AttestationResponse.RegistrationResponse(
|
|
||||||
clientDataJson = response.clientDataJson.base64EncodeForFido2Response(),
|
clientDataJson = response.clientDataJson.base64EncodeForFido2Response(),
|
||||||
attestationObject = response.attestationObject.base64EncodeForFido2Response(),
|
attestationObject = response.attestationObject.base64EncodeForFido2Response(),
|
||||||
transports = response.transports,
|
transports = response.transports.takeUnless {
|
||||||
|
// Setting transports as null, otherwise Binance labels the passkey broken
|
||||||
|
// PM-26734 remove this flow if not necessary anymore
|
||||||
|
callingPackageName == BINANCE_PACKAGE_NAME
|
||||||
|
},
|
||||||
publicKeyAlgorithm = response.publicKeyAlgorithm,
|
publicKeyAlgorithm = response.publicKeyAlgorithm,
|
||||||
publicKey = response.publicKey?.base64EncodeForFido2Response(),
|
publicKey = response.publicKey?.base64EncodeForFido2Response(),
|
||||||
authenticatorData = response.authenticatorData.base64EncodeForFido2Response(),
|
authenticatorData = response.authenticatorData.base64EncodeForFido2Response(),
|
||||||
),
|
)
|
||||||
|
|
||||||
|
return Fido2AttestationResponse(
|
||||||
|
id = id,
|
||||||
|
type = ty,
|
||||||
|
rawId = rawId.base64EncodeForFido2Response(),
|
||||||
|
response = registrationResponse,
|
||||||
clientExtensionResults = clientExtensionResults
|
clientExtensionResults = clientExtensionResults
|
||||||
.credProps
|
.credProps
|
||||||
?.rk
|
?.rk
|
||||||
@ -34,6 +43,7 @@ fun PublicKeyCredentialAuthenticatorAttestationResponse.toAndroidAttestationResp
|
|||||||
} ?: Fido2AttestationResponse.ClientExtensionResults(),
|
} ?: Fido2AttestationResponse.ClientExtensionResults(),
|
||||||
authenticatorAttachment = authenticatorAttachment,
|
authenticatorAttachment = authenticatorAttachment,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attestation response fields of type [ByteArray] must be base 64 encoded in a url safe format
|
* Attestation response fields of type [ByteArray] must be base 64 encoded in a url safe format
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class PublicKeyCredentialAuthenticatorAttestationResponseExtensionsTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `authenticatorAttachment should be null when SDK value is null`() {
|
fun `authenticatorAttachment should be null when SDK value is null`() {
|
||||||
val mockSdkResponse = createMockSdkAttestationResponse(number = 1)
|
val mockSdkResponse = createMockSdkAttestationResponse(number = 1)
|
||||||
val result = mockSdkResponse.toAndroidAttestationResponse()
|
val result = mockSdkResponse.toAndroidAttestationResponse(callingPackageName = "")
|
||||||
assertNull(result.authenticatorAttachment)
|
assertNull(result.authenticatorAttachment)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,14 +43,14 @@ class PublicKeyCredentialAuthenticatorAttestationResponseExtensionsTest {
|
|||||||
number = 1,
|
number = 1,
|
||||||
authenticatorAttachment = "mockAuthenticatorAttachment",
|
authenticatorAttachment = "mockAuthenticatorAttachment",
|
||||||
)
|
)
|
||||||
val result = mockSdkResponse.toAndroidAttestationResponse()
|
val result = mockSdkResponse.toAndroidAttestationResponse(callingPackageName = "")
|
||||||
assertNotNull(result.authenticatorAttachment)
|
assertNotNull(result.authenticatorAttachment)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `clientExtensionResults should be populated when SDK value is null`() {
|
fun `clientExtensionResults should be populated when SDK value is null`() {
|
||||||
val mockSdkResponse = createMockSdkAttestationResponse(number = 1)
|
val mockSdkResponse = createMockSdkAttestationResponse(number = 1)
|
||||||
val result = mockSdkResponse.toAndroidAttestationResponse()
|
val result = mockSdkResponse.toAndroidAttestationResponse(callingPackageName = "")
|
||||||
assertNotNull(result.clientExtensionResults)
|
assertNotNull(result.clientExtensionResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,9 +63,41 @@ class PublicKeyCredentialAuthenticatorAttestationResponseExtensionsTest {
|
|||||||
authenticatorDisplayName = null,
|
authenticatorDisplayName = null,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
val result = mockSdkResponse.toAndroidAttestationResponse()
|
val result = mockSdkResponse.toAndroidAttestationResponse(callingPackageName = "")
|
||||||
assert(result.clientExtensionResults.credentialProperties?.residentKey ?: false)
|
assert(result.clientExtensionResults.credentialProperties?.residentKey ?: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
|
@Test
|
||||||
|
fun `toAndroidAttestationResponse should build specific response when package name is Binance`() {
|
||||||
|
val binancePackageName = "com.binance.dev"
|
||||||
|
val mockSdkResponse = createMockSdkAttestationResponse(number = 1)
|
||||||
|
|
||||||
|
val result = mockSdkResponse.toAndroidAttestationResponse(callingPackageName = binancePackageName)
|
||||||
|
|
||||||
|
assertNull(result.response.transports)
|
||||||
|
assertNotNull(result.response.publicKey)
|
||||||
|
assertNotNull(result.response.publicKeyAlgorithm)
|
||||||
|
assertNotNull(result.response.authenticatorData)
|
||||||
|
assertNotNull(result.response.clientDataJson)
|
||||||
|
assertNotNull(result.response.attestationObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
|
@Test
|
||||||
|
fun `toAndroidAttestationResponse should build full response for any package name other than Binance`() {
|
||||||
|
val otherPackageName = "com.any.app"
|
||||||
|
val mockSdkResponse = createMockSdkAttestationResponse(number = 1)
|
||||||
|
|
||||||
|
val result = mockSdkResponse.toAndroidAttestationResponse(callingPackageName = otherPackageName)
|
||||||
|
|
||||||
|
assertNotNull(result.response.transports)
|
||||||
|
assertNotNull(result.response.publicKey)
|
||||||
|
assertNotNull(result.response.publicKeyAlgorithm)
|
||||||
|
assertNotNull(result.response.authenticatorData)
|
||||||
|
assertNotNull(result.response.clientDataJson)
|
||||||
|
assertNotNull(result.response.attestationObject)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createMockSdkAttestationResponse(
|
private fun createMockSdkAttestationResponse(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user