From cc9fb988c07943376418f1732389a2ee211766a6 Mon Sep 17 00:00:00 2001 From: Aditya Gupta Date: Mon, 27 Feb 2023 12:10:07 +0530 Subject: [PATCH] Implemented biometric authentication * Upstream sdk version is needed to compile the imported libraries Signed-off-by: aditya-gupta99 --- build.gradle | 2 +- mifosng-android/build.gradle | 5 + .../passcode/BiometricAuthentication.kt | 104 ++++++++++++++++++ .../mifosxdroid/passcode/PassCodeActivity.kt | 22 ++++ .../src/main/res/values/strings.xml | 2 + 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 mifosng-android/src/main/java/com/mifos/mifosxdroid/passcode/BiometricAuthentication.kt diff --git a/build.gradle b/build.gradle index ebb1cacc589..daf38f79eca 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ ext { // Sdk and tools minSdkVersion = 15 targetSdkVersion = 32 - compileSdkVersion = 32 + compileSdkVersion = 33 buildToolsVersion = '28.0.3' // App dependencies diff --git a/mifosng-android/build.gradle b/mifosng-android/build.gradle index 7a33812adfa..a5496088001 100755 --- a/mifosng-android/build.gradle +++ b/mifosng-android/build.gradle @@ -262,6 +262,11 @@ dependencies { implementation 'androidx.cardview:cardview:1.0.0' //preferences implementation "androidx.preference:preference:$preference" + + implementation("androidx.biometric:biometric:1.2.0-alpha05") + + implementation 'androidx.appcompat:appcompat:1.3.1' + } /* All direct/transitive dependencies shared between your test and production APKs need to be diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/passcode/BiometricAuthentication.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/passcode/BiometricAuthentication.kt new file mode 100644 index 00000000000..5c8c6481842 --- /dev/null +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/passcode/BiometricAuthentication.kt @@ -0,0 +1,104 @@ +package com.mifos.mifosxdroid.passcode + +import android.content.Intent +import androidx.biometric.BiometricManager +import android.os.Build +import android.provider.Settings +import android.provider.Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED +import androidx.activity.result.ActivityResultLauncher +import androidx.biometric.BiometricPrompt +import androidx.core.content.ContextCompat +import androidx.fragment.app.FragmentActivity +import com.mifos.mifosxdroid.HomeActivity +import com.mifos.mifosxdroid.R + +open class BiometricAuthentication( + val context: FragmentActivity, +) { + private val executor = ContextCompat.getMainExecutor(context) + private val callback = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + object : BiometricPrompt.AuthenticationCallback() { + override fun onAuthenticationFailed() { + super.onAuthenticationFailed() + } + + override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { + super.onAuthenticationSucceeded(result) + val intent= Intent(context, HomeActivity::class.java) + context.startActivity(intent) + } + + override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { + super.onAuthenticationError(errorCode, errString) + } + } + } else { + TODO("VERSION.SDK_INT < P") + } + + private val biometricPrompt = BiometricPrompt(context, executor, callback) + + + + fun launchBiometricEnrollment(resultLauncher: ActivityResultLauncher) { + val intent: Intent = when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> { + Intent(Settings.ACTION_BIOMETRIC_ENROLL).putExtra( + EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, + BiometricManager.Authenticators.BIOMETRIC_STRONG or BiometricManager.Authenticators.BIOMETRIC_WEAK + ) + } + Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> { + Intent(Settings.ACTION_FINGERPRINT_ENROLL) + } + else -> { + Intent(Settings.ACTION_SECURITY_SETTINGS) + } + } + resultLauncher.launch(intent) + } + + fun getBiometricCapabilities(): BiometricCapability { + val biometricManager = BiometricManager.from(context) + return when (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL)) { + BiometricManager.BIOMETRIC_SUCCESS -> { + BiometricCapability.HAS_BIOMETRIC_AUTH + } + BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> { + BiometricCapability.NOT_SUPPORTED + } + BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> { + BiometricCapability.NOT_SUPPORTED + } + BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> { + BiometricCapability.NOT_ENROLLED + } + BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> { + BiometricCapability.SECURITY_UPDATE_REQUIRED + } + BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> { + BiometricCapability.NOT_SUPPORTED + } + BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> { + BiometricCapability.NOT_SUPPORTED + } + else -> { + BiometricCapability.NOT_SUPPORTED + } + } + } + + fun authenticateWithBiometrics() { + val promptInfo = BiometricPrompt.PromptInfo.Builder().apply { + setTitle(context.getString(R.string.unlocked_mifos)) + setDescription(context.getString(R.string.text_description_biometrics_dialog)) + setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL) + }.build() + + biometricPrompt.authenticate(promptInfo) + } +} + +enum class BiometricCapability { + HAS_BIOMETRIC_AUTH, NOT_ENROLLED, SECURITY_UPDATE_REQUIRED, NOT_SUPPORTED +} \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/passcode/PassCodeActivity.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/passcode/PassCodeActivity.kt index e773579b292..e2e0b08bf44 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/passcode/PassCodeActivity.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/passcode/PassCodeActivity.kt @@ -3,6 +3,7 @@ package com.mifos.mifosxdroid.passcode; import android.content.Intent import android.os.Bundle import android.view.View +import androidx.appcompat.widget.AppCompatButton import com.mifos.mifosxdroid.HomeActivity import com.mifos.mifosxdroid.R import com.mifos.mifosxdroid.SplashScreenActivity @@ -23,6 +24,20 @@ class PassCodeActivity : MifosPassCodeActivity() { currPassCode = it.getStringExtra(Constants.CURR_PASSWORD) isToUpdatePassCode = it.getBooleanExtra(Constants.IS_TO_UPDATE_PASS_CODE, false) } + if(findViewById(R.id.btn_save).text.equals("Login with biometric")){ + BiometricAuthentication(this).authenticateWithBiometrics() + } + if(BiometricAuthentication(this).getBiometricCapabilities()==BiometricCapability.HAS_BIOMETRIC_AUTH){ + val btn=findViewById(R.id.btn_save) + if (btn.visibility==View.GONE){ + btn.visibility=View.VISIBLE + btn.text="Login with biometric" + btn.setOnClickListener { + BiometricAuthentication(this).authenticateWithBiometrics() + } + } + } + } override fun showToaster(view: View?, msg: Int) { @@ -51,4 +66,11 @@ class PassCodeActivity : MifosPassCodeActivity() { } finish() } + + override fun onResume() { + if(findViewById(R.id.btn_save).text.equals("Login with biometric")){ + BiometricAuthentication(this).authenticateWithBiometrics() + } + super.onResume() + } } diff --git a/mifosng-android/src/main/res/values/strings.xml b/mifosng-android/src/main/res/values/strings.xml index 8e158453661..9413ac9b80a 100755 --- a/mifosng-android/src/main/res/values/strings.xml +++ b/mifosng-android/src/main/res/values/strings.xml @@ -895,6 +895,8 @@ Passcode Change Passcode Change App Passcode + Unlock Mifos + Use your with PIN, Pattern, Password Face or fingerprint Currency Account Number