diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/OneWelcomeWrapperErrors.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/OneWelcomeWrapperErrors.kt index f9e51371..c4e92e48 100644 --- a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/OneWelcomeWrapperErrors.kt +++ b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/OneWelcomeWrapperErrors.kt @@ -31,7 +31,7 @@ enum class OneWelcomeWrapperErrors(val code: Int, val message: String) { CONFIG_ERROR(8059, "Something went wrong while setting the configuration"), // Android only BIOMETRIC_AUTHENTICATION_NOT_AVAILABLE(8060, "Biometric authentication is not supported on this device"), - NOT_IN_PROGRESS_BIOMETRIC_AUTHENTICATION(8062, "Biometric Authentication is currently not in progress"), // Android only + BIOMETRIC_AUTHENTICATION_NOT_IN_PROGRESS(8062, "Biometric Authentication is currently not in progress"), // Android only // Only used for internal testing UNEXPECTED_ERROR_TYPE(8999, "An unexpected error type was returned"), // Android only diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/PigeonInterface.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/PigeonInterface.kt index e93e42ce..6a94d8b9 100644 --- a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/PigeonInterface.kt +++ b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/PigeonInterface.kt @@ -18,7 +18,9 @@ import com.onegini.mobile.sdk.flutter.pigeonPlugin.UserClientApi import com.onegini.mobile.sdk.flutter.useCases.AuthenticateDeviceUseCase import com.onegini.mobile.sdk.flutter.useCases.AuthenticateUserImplicitlyUseCase import com.onegini.mobile.sdk.flutter.useCases.AuthenticateUserUseCase -import com.onegini.mobile.sdk.flutter.useCases.BiometricAuthenticationUseCase +import com.onegini.mobile.sdk.flutter.useCases.BiometricShowPromptUseCase +import com.onegini.mobile.sdk.flutter.useCases.BiometricFallbackToPinUseCase +import com.onegini.mobile.sdk.flutter.useCases.BiometricDenyAuthenticationRequestUseCase import com.onegini.mobile.sdk.flutter.useCases.CancelBrowserRegistrationUseCase import com.onegini.mobile.sdk.flutter.useCases.CancelCustomRegistrationActionUseCase import com.onegini.mobile.sdk.flutter.useCases.ChangePinUseCase @@ -53,7 +55,6 @@ import com.onegini.mobile.sdk.flutter.useCases.SetPreferredAuthenticatorUseCase import com.onegini.mobile.sdk.flutter.useCases.StartAppUseCase import com.onegini.mobile.sdk.flutter.useCases.SubmitCustomRegistrationActionUseCase import com.onegini.mobile.sdk.flutter.useCases.ValidatePinWithPolicyUseCase -import com.onegini.mobile.sdk.flutter.helpers.BiometricAuthRequestType import javax.inject.Inject open class PigeonInterface : UserClientApi, ResourceMethodApi { @@ -169,7 +170,13 @@ open class PigeonInterface : UserClientApi, ResourceMethodApi { lateinit var otpAcceptAuthenticationRequestUseCase: OtpAcceptAuthenticationRequestUseCase @Inject - lateinit var biometricAuthUseCase: BiometricAuthenticationUseCase + lateinit var biometricShowPromptUseCase: BiometricShowPromptUseCase + + @Inject + lateinit var biometricFallbackToPinUseCase: BiometricFallbackToPinUseCase + + @Inject + lateinit var biometricDenyAuthRequestUseCase: BiometricDenyAuthenticationRequestUseCase @Inject lateinit var oneginiSDK: OneginiSDK @@ -347,15 +354,15 @@ open class PigeonInterface : UserClientApi, ResourceMethodApi { } override fun showBiometricPrompt(messages: OWBiometricMessages, callback: (Result) -> Unit) { - biometricAuthUseCase(BiometricAuthRequestType.showprompt, messages, callback) + biometricShowPromptUseCase(messages, callback) } override fun biometricFallbackToPin(callback: (Result) -> Unit) { - biometricAuthUseCase(BiometricAuthRequestType.fallbacktopin, OWBiometricMessages("", "", ""), callback) + biometricFallbackToPinUseCase(callback) } override fun biometricDenyAuthenticationRequest(callback: (Result) -> Unit) { - biometricAuthUseCase(BiometricAuthRequestType.denyauthrequest, OWBiometricMessages("", "", ""), callback) + biometricDenyAuthRequestUseCase(callback) } } diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/facade/BiometricPromptFacade.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/facade/BiometricPromptFacade.kt new file mode 100644 index 00000000..4ac61cf1 --- /dev/null +++ b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/facade/BiometricPromptFacade.kt @@ -0,0 +1,10 @@ +package com.onegini.mobile.sdk.flutter.facade + +import android.app.Activity +import com.onegini.mobile.sdk.flutter.handlers.BiometricAuthenticationRequestHandler +import com.onegini.mobile.sdk.flutter.pigeonPlugin.OWBiometricMessages + +interface BiometricPromptFacade { + fun showPrompt(messages: OWBiometricMessages, activity: Activity, biometricAuthRequestHandler: BiometricAuthenticationRequestHandler) + fun closePrompt() +} \ No newline at end of file diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/facade/BiometricPromptFacadeImpl.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/facade/BiometricPromptFacadeImpl.kt new file mode 100644 index 00000000..0dd7d5f4 --- /dev/null +++ b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/facade/BiometricPromptFacadeImpl.kt @@ -0,0 +1,44 @@ +package com.onegini.mobile.sdk.flutter.facade + +import javax.inject.Inject +import javax.inject.Singleton +import android.app.Activity +import androidx.fragment.app.FragmentActivity +import androidx.biometric.BiometricPrompt +import androidx.core.content.ContextCompat +import com.onegini.mobile.sdk.flutter.handlers.BiometricAuthenticationRequestHandler +import com.onegini.mobile.sdk.flutter.pigeonPlugin.OWBiometricMessages + +@Singleton +class BiometricPromptFacadeImpl @Inject constructor() : BiometricPromptFacade { + + private lateinit var biometricPrompt: BiometricPrompt + + override fun showPrompt(biometricMessages: OWBiometricMessages, activity: Activity, biometricRequestHandler: BiometricAuthenticationRequestHandler) { + val fragmentActivity = activity as FragmentActivity + biometricPrompt = BiometricPrompt(fragmentActivity, ContextCompat.getMainExecutor(fragmentActivity), object: BiometricPrompt.AuthenticationCallback() { + override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { + biometricRequestHandler.CALLBACK?.onBiometricAuthenticationError(errorCode) + } + + override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { + biometricRequestHandler.CALLBACK?.userAuthenticatedSuccessfully() + } + + override fun onAuthenticationFailed() { + } + }) + + val promptInfo: BiometricPrompt.PromptInfo = BiometricPrompt.PromptInfo.Builder() + .setTitle(biometricMessages.title) + .setSubtitle(biometricMessages.subTitle) + .setNegativeButtonText(biometricMessages.negativeButtonText) + .setDescription(biometricMessages.description) + .build() + biometricPrompt.authenticate(promptInfo, biometricRequestHandler.CRYPTO_OBJECT!!) + } + + override fun closePrompt() { + biometricPrompt.cancelAuthentication() + } +} \ No newline at end of file diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/handlers/BiometricAuthenticationRequestHandler.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/handlers/BiometricAuthenticationRequestHandler.kt index 9081ad25..9e631ff4 100644 --- a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/handlers/BiometricAuthenticationRequestHandler.kt +++ b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/handlers/BiometricAuthenticationRequestHandler.kt @@ -3,10 +3,7 @@ package com.onegini.mobile.sdk.flutter.handlers import androidx.biometric.BiometricPrompt import com.onegini.mobile.sdk.android.handlers.request.OneginiBiometricAuthenticationRequestHandler import com.onegini.mobile.sdk.android.handlers.request.callback.OneginiBiometricCallback -import com.onegini.mobile.sdk.android.model.entity.UserProfile import com.onegini.mobile.sdk.flutter.pigeonPlugin.NativeCallFlutterApi -import com.onegini.mobile.sdk.flutter.OneWelcomeWrapperErrors.NOT_IN_PROGRESS_BIOMETRIC_AUTHENTICATION -import com.onegini.mobile.sdk.flutter.helpers.SdkError import javax.inject.Inject import javax.inject.Singleton diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/helpers/BiometricAuthRequestType.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/helpers/BiometricAuthRequestType.kt deleted file mode 100644 index 7cb3cdd2..00000000 --- a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/helpers/BiometricAuthRequestType.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.onegini.mobile.sdk.flutter.helpers - -enum class BiometricAuthRequestType { - showprompt, - fallbacktopin, - denyauthrequest -} diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/module/FacadeModule.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/module/FacadeModule.kt index bdb65a59..05371ba8 100644 --- a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/module/FacadeModule.kt +++ b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/module/FacadeModule.kt @@ -2,6 +2,8 @@ package com.onegini.mobile.sdk.flutter.module import com.onegini.mobile.sdk.flutter.facade.UriFacade import com.onegini.mobile.sdk.flutter.facade.UriFacadeImpl +import com.onegini.mobile.sdk.flutter.facade.BiometricPromptFacade +import com.onegini.mobile.sdk.flutter.facade.BiometricPromptFacadeImpl import dagger.Binds import dagger.Module @@ -9,4 +11,7 @@ import dagger.Module interface FacadeModule { @Binds fun bindUriFacade(uriFacade: UriFacadeImpl): UriFacade -} + + @Binds + fun bindBiometricPromptFacade(biometricPromptFacade: BiometricPromptFacadeImpl): BiometricPromptFacade +} \ No newline at end of file diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricAuthenticationUseCase.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricAuthenticationUseCase.kt deleted file mode 100644 index 5c0d6270..00000000 --- a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricAuthenticationUseCase.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.onegini.mobile.sdk.flutter.useCases - -import android.app.Activity -import androidx.fragment.app.FragmentActivity -import androidx.biometric.BiometricPrompt -import androidx.core.content.ContextCompat -import com.onegini.mobile.sdk.flutter.OneWelcomeWrapperErrors.NOT_IN_PROGRESS_BIOMETRIC_AUTHENTICATION -import com.onegini.mobile.sdk.flutter.handlers.BiometricAuthenticationRequestHandler -import com.onegini.mobile.sdk.flutter.helpers.SdkError -import com.onegini.mobile.sdk.flutter.helpers.BiometricAuthRequestType -import com.onegini.mobile.sdk.flutter.pigeonPlugin.OWBiometricMessages -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class BiometricAuthenticationUseCase @Inject constructor(private val activity: Activity, - private val biometricAuthRequestHandler: BiometricAuthenticationRequestHandler) { - private lateinit var fragmentActivity: FragmentActivity - private lateinit var biometricRequestHandler: BiometricAuthenticationRequestHandler - private lateinit var biometricPrompt: BiometricPrompt - private lateinit var biometricMessages: OWBiometricMessages - - operator fun invoke(requestType: BiometricAuthRequestType, messages: OWBiometricMessages, callback: (Result) -> Unit) { - biometricRequestHandler = biometricAuthRequestHandler - - if (biometricRequestHandler.CALLBACK == null) { - return callback(Result.failure(SdkError(NOT_IN_PROGRESS_BIOMETRIC_AUTHENTICATION).pigeonError())) - } - - when (requestType) { - BiometricAuthRequestType.showprompt -> { - fragmentActivity = activity as FragmentActivity - this.biometricMessages = messages - showPrompt() - } - BiometricAuthRequestType.fallbacktopin -> { - biometricRequestHandler.CALLBACK?.fallbackToPin() - biometricPrompt.cancelAuthentication() - } - - BiometricAuthRequestType.denyauthrequest -> { - biometricRequestHandler.CALLBACK?.denyAuthenticationRequest() - biometricPrompt.cancelAuthentication() - } - } - return callback(Result.success(Unit)); - } - - private fun showPrompt() { - biometricPrompt = BiometricPrompt(fragmentActivity, ContextCompat.getMainExecutor(fragmentActivity), object: BiometricPrompt.AuthenticationCallback() { - override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { - biometricRequestHandler.CALLBACK?.onBiometricAuthenticationError(errorCode) - } - - override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { - biometricRequestHandler.CALLBACK?.userAuthenticatedSuccessfully() - } - - override fun onAuthenticationFailed() { - } - }) - - val promptInfo: BiometricPrompt.PromptInfo = BiometricPrompt.PromptInfo.Builder() - .setTitle(biometricMessages.title) - .setSubtitle(biometricMessages.subTitle) - .setNegativeButtonText(biometricMessages.negativeButtonText) - .setDescription(biometricMessages.description) - .build() - biometricPrompt.authenticate(promptInfo, biometricRequestHandler.CRYPTO_OBJECT!!) - } -} \ No newline at end of file diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricDenyAuthenticationRequestUseCase.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricDenyAuthenticationRequestUseCase.kt new file mode 100644 index 00000000..e1003983 --- /dev/null +++ b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricDenyAuthenticationRequestUseCase.kt @@ -0,0 +1,21 @@ +package com.onegini.mobile.sdk.flutter.useCases + +import com.onegini.mobile.sdk.flutter.handlers.BiometricAuthenticationRequestHandler +import com.onegini.mobile.sdk.flutter.facade.BiometricPromptFacade +import com.onegini.mobile.sdk.flutter.OneWelcomeWrapperErrors.BIOMETRIC_AUTHENTICATION_NOT_IN_PROGRESS +import com.onegini.mobile.sdk.flutter.helpers.SdkError +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class BiometricDenyAuthenticationRequestUseCase @Inject constructor(private val biometricAuthRequestHandler: BiometricAuthenticationRequestHandler, + private val biometricPromptFacade: BiometricPromptFacade) { + operator fun invoke(callback: (Result) -> Unit){ + if (biometricAuthRequestHandler.CALLBACK == null) { + return callback(Result.failure(SdkError(BIOMETRIC_AUTHENTICATION_NOT_IN_PROGRESS).pigeonError())) + } + biometricAuthRequestHandler.CALLBACK?.denyAuthenticationRequest() + biometricPromptFacade.closePrompt() + return callback(Result.success(Unit)) + } +} diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricFallbackToPinUseCase.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricFallbackToPinUseCase.kt new file mode 100644 index 00000000..9fbcb0bf --- /dev/null +++ b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricFallbackToPinUseCase.kt @@ -0,0 +1,21 @@ +package com.onegini.mobile.sdk.flutter.useCases + +import com.onegini.mobile.sdk.flutter.handlers.BiometricAuthenticationRequestHandler +import com.onegini.mobile.sdk.flutter.facade.BiometricPromptFacade +import com.onegini.mobile.sdk.flutter.OneWelcomeWrapperErrors.BIOMETRIC_AUTHENTICATION_NOT_IN_PROGRESS +import com.onegini.mobile.sdk.flutter.helpers.SdkError +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class BiometricFallbackToPinUseCase @Inject constructor(private val biometricAuthRequestHandler: BiometricAuthenticationRequestHandler, + private val biometricPromptFacade: BiometricPromptFacade) { + operator fun invoke(callback: (Result) -> Unit) { + if (biometricAuthRequestHandler.CALLBACK == null) { + return callback(Result.failure(SdkError(BIOMETRIC_AUTHENTICATION_NOT_IN_PROGRESS).pigeonError())) + } + biometricAuthRequestHandler.CALLBACK?.fallbackToPin() + biometricPromptFacade.closePrompt() + return callback(Result.success(Unit)) + } +} \ No newline at end of file diff --git a/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricShowPromptUseCase.kt b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricShowPromptUseCase.kt new file mode 100644 index 00000000..bf9b807a --- /dev/null +++ b/android/src/main/kotlin/com/onegini/mobile/sdk/flutter/useCases/BiometricShowPromptUseCase.kt @@ -0,0 +1,26 @@ +package com.onegini.mobile.sdk.flutter.useCases + +import android.app.Activity +import androidx.fragment.app.FragmentActivity +import androidx.biometric.BiometricPrompt +import androidx.core.content.ContextCompat +import com.onegini.mobile.sdk.flutter.OneWelcomeWrapperErrors.BIOMETRIC_AUTHENTICATION_NOT_IN_PROGRESS +import com.onegini.mobile.sdk.flutter.handlers.BiometricAuthenticationRequestHandler +import com.onegini.mobile.sdk.flutter.helpers.SdkError +import com.onegini.mobile.sdk.flutter.pigeonPlugin.OWBiometricMessages +import com.onegini.mobile.sdk.flutter.facade.BiometricPromptFacade +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class BiometricShowPromptUseCase @Inject constructor(private val activity: Activity, + private val biometricAuthRequestHandler: BiometricAuthenticationRequestHandler, + private val biometricPromptFacade: BiometricPromptFacade) { + operator fun invoke(messages: OWBiometricMessages, callback: (Result) -> Unit) { + if (biometricAuthRequestHandler.CALLBACK == null) { + return callback(Result.failure(SdkError(BIOMETRIC_AUTHENTICATION_NOT_IN_PROGRESS).pigeonError())) + } + biometricPromptFacade.showPrompt(messages, activity, biometricAuthRequestHandler) + return callback(Result.success(Unit)) + } +} \ No newline at end of file