[PM-9409] Complete FIDO 2 assertion with appropriate response (#3615)

This commit is contained in:
Patrick Honkonen
2024-07-25 10:33:14 -04:00
committed by GitHub
parent 8ffd14c2fb
commit 793971c3a3
6 changed files with 260 additions and 5 deletions
@@ -0,0 +1,22 @@
package com.x8bit.bitwarden.data.autofill.fido2.model
/**
* Represents possible outcomes of a FIDO 2 credential assertion request.
*/
sealed class Fido2CredentialAssertionResult {
/**
* Indicates the assertion request completed and [responseJson] was successfully generated.
*/
data class Success(val responseJson: String) : Fido2CredentialAssertionResult()
/**
* Indicates there was an error and the assertion was not successful.
*/
data object Error : Fido2CredentialAssertionResult()
/**
* Indicates assertion was cancelled by the user.
*/
data object Cancelled : Fido2CredentialAssertionResult()
}
@@ -1,5 +1,6 @@
package com.x8bit.bitwarden.ui.autofill.fido2.manager
import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2CredentialAssertionResult
import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2RegisterCredentialResult
/**
@@ -11,4 +12,9 @@ interface Fido2CompletionManager {
* Completes the FIDO 2 registration process with the provided [result].
*/
fun completeFido2Registration(result: Fido2RegisterCredentialResult)
/**
* Complete the FIDO 2 credential assertion process with the provided [result].
*/
fun completeFido2Assertion(result: Fido2CredentialAssertionResult)
}
@@ -5,21 +5,25 @@ import android.content.Intent
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.credentials.CreatePublicKeyCredentialResponse
import androidx.credentials.GetCredentialResponse
import androidx.credentials.PublicKeyCredential
import androidx.credentials.exceptions.CreateCredentialCancellationException
import androidx.credentials.exceptions.CreateCredentialUnknownException
import androidx.credentials.exceptions.GetCredentialCancellationException
import androidx.credentials.exceptions.GetCredentialUnknownException
import androidx.credentials.provider.PendingIntentHandler
import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2CredentialAssertionResult
import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2RegisterCredentialResult
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
/**
* Primary implementation of [Fido2CompletionManager].
* Primary implementation of [Fido2CompletionManager] when the build version is
* UPSIDE_DOWN_CAKE (34) or above.
*/
@OmitFromCoverage
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
class Fido2CompletionManagerImpl(
private val activity: Activity,
) : Fido2CompletionManager {
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
override fun completeFido2Registration(result: Fido2RegisterCredentialResult) {
activity.also {
val intent = Intent()
@@ -54,4 +58,39 @@ class Fido2CompletionManagerImpl(
it.finish()
}
}
override fun completeFido2Assertion(result: Fido2CredentialAssertionResult) {
activity.also {
val intent = Intent()
when (result) {
Fido2CredentialAssertionResult.Cancelled -> {
PendingIntentHandler
.setGetCredentialException(
intent = intent,
exception = GetCredentialCancellationException(),
)
}
Fido2CredentialAssertionResult.Error -> {
PendingIntentHandler
.setGetCredentialException(
intent = intent,
exception = GetCredentialUnknownException(),
)
}
is Fido2CredentialAssertionResult.Success -> {
PendingIntentHandler
.setGetCredentialResponse(
intent = intent,
response = GetCredentialResponse(
credential = PublicKeyCredential(result.responseJson),
),
)
}
}
it.setResult(Activity.RESULT_OK, intent)
it.finish()
}
}
}
@@ -0,0 +1,14 @@
package com.x8bit.bitwarden.ui.autofill.fido2.manager
import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2CredentialAssertionResult
import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2RegisterCredentialResult
/**
* A no-op implementation of [Fido2CompletionManagerImpl] provided when the build version is below
* UPSIDE_DOWN_CAKE (34). These versions do not support [androidx.credentials.CredentialProvider].
*/
object Fido2CompletionManagerUnsupportedApiImpl : Fido2CompletionManager {
override fun completeFido2Registration(result: Fido2RegisterCredentialResult) = Unit
override fun completeFido2Assertion(result: Fido2CredentialAssertionResult) = Unit
}
@@ -3,6 +3,7 @@
package com.x8bit.bitwarden.ui.platform.composition
import android.app.Activity
import android.os.Build
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocal
import androidx.compose.runtime.CompositionLocalProvider
@@ -10,8 +11,10 @@ import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.platform.LocalContext
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
import com.x8bit.bitwarden.ui.autofill.fido2.manager.Fido2CompletionManager
import com.x8bit.bitwarden.ui.autofill.fido2.manager.Fido2CompletionManagerImpl
import com.x8bit.bitwarden.ui.autofill.fido2.manager.Fido2CompletionManagerUnsupportedApiImpl
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManager
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManagerImpl
import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManager
@@ -29,13 +32,19 @@ import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManagerImp
@Composable
fun LocalManagerProvider(content: @Composable () -> Unit) {
val activity = LocalContext.current as Activity
val fido2CompletionManager =
if (isBuildVersionBelow(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) {
Fido2CompletionManagerUnsupportedApiImpl
} else {
Fido2CompletionManagerImpl(activity)
}
CompositionLocalProvider(
LocalPermissionsManager provides PermissionsManagerImpl(activity),
LocalIntentManager provides IntentManagerImpl(activity),
LocalExitManager provides ExitManagerImpl(activity),
LocalBiometricsManager provides BiometricsManagerImpl(activity),
LocalNfcManager provides NfcManagerImpl(activity),
LocalFido2CompletionManager provides Fido2CompletionManagerImpl(activity),
LocalFido2CompletionManager provides fido2CompletionManager,
) {
content()
}