diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-03-30 00:45:41 -0600 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-03-30 03:23:32 -0600 |
commit | 09b40cdec7d096afac11d42d194934fa7c011ab1 (patch) | |
tree | 78216aaa463f35795c1755a6c0ab0a1d15e55550 /ui/src/main/java/com/wireguard/android/util/BiometricAuthenticator.kt | |
parent | BiometricAuthenticator: implement biometric authentication for sensitive operations (diff) | |
download | wireguard-android-09b40cdec7d096afac11d42d194934fa7c011ab1.tar.xz wireguard-android-09b40cdec7d096afac11d42d194934fa7c011ab1.zip |
BiometricAuthenticator: rework logic and bugs
Otherwise there's a frameworks bug that causes the fragment's activity
to become null.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to '')
-rw-r--r-- | ui/src/main/java/com/wireguard/android/util/BiometricAuthenticator.kt | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/ui/src/main/java/com/wireguard/android/util/BiometricAuthenticator.kt b/ui/src/main/java/com/wireguard/android/util/BiometricAuthenticator.kt index cf81f768..aed8a4f2 100644 --- a/ui/src/main/java/com/wireguard/android/util/BiometricAuthenticator.kt +++ b/ui/src/main/java/com/wireguard/android/util/BiometricAuthenticator.kt @@ -5,15 +5,21 @@ package com.wireguard.android.util +import android.annotation.SuppressLint +import android.app.KeyguardManager +import android.content.Context +import android.os.Build import android.os.Handler import android.util.Log import androidx.annotation.StringRes import androidx.biometric.BiometricConstants import androidx.biometric.BiometricManager import androidx.biometric.BiometricPrompt -import androidx.fragment.app.FragmentActivity +import androidx.core.content.getSystemService +import androidx.fragment.app.Fragment import com.wireguard.android.R + object BiometricAuthenticator { private const val TAG = "WireGuard/BiometricAuthenticator" private val handler = Handler() @@ -25,12 +31,25 @@ object BiometricAuthenticator { object Cancelled : Result() } + @SuppressLint("PrivateApi") + private fun isPinEnabled(context: Context): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + return context.getSystemService<KeyguardManager>()!!.isDeviceSecure + return try { + val lockUtilsClass = Class.forName("com.android.internal.widget.LockPatternUtils") + val lockUtils = lockUtilsClass.getConstructor(Context::class.java).newInstance(context) + val method = lockUtilsClass.getMethod("isLockScreenDisabled") + !(method.invoke(lockUtils) as Boolean) + } catch (e: Exception) { + false + } + } + fun authenticate( @StringRes dialogTitleRes: Int, - fragmentActivity: FragmentActivity, + fragment: Fragment, callback: (Result) -> Unit ) { - val biometricManager = BiometricManager.from(fragmentActivity) val authCallback = object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) @@ -44,13 +63,13 @@ object BiometricAuthenticator { BiometricConstants.ERROR_NO_BIOMETRICS, BiometricConstants.ERROR_NO_DEVICE_CREDENTIAL -> { Result.HardwareUnavailableOrDisabled } - else -> Result.Failure(errorCode, fragmentActivity.getString(R.string.biometric_auth_error_reason, errString)) + else -> Result.Failure(errorCode, fragment.getString(R.string.biometric_auth_error_reason, errString)) }) } override fun onAuthenticationFailed() { super.onAuthenticationFailed() - callback(Result.Failure(null, fragmentActivity.getString(R.string.biometric_auth_error))) + callback(Result.Failure(null, fragment.getString(R.string.biometric_auth_error))) } override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { @@ -58,13 +77,12 @@ object BiometricAuthenticator { callback(Result.Success(result.cryptoObject)) } } - val biometricPrompt = BiometricPrompt(fragmentActivity, { handler.post(it) }, authCallback) + val biometricPrompt = BiometricPrompt(fragment, { handler.post(it) }, authCallback) val promptInfo = BiometricPrompt.PromptInfo.Builder() - .setTitle(fragmentActivity.getString(dialogTitleRes)) + .setTitle(fragment.getString(dialogTitleRes)) .setDeviceCredentialAllowed(true) .build() - - if (biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) { + if (BiometricManager.from(fragment.requireContext()).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS || isPinEnabled(fragment.requireContext())) { biometricPrompt.authenticate(promptInfo) } else { callback(Result.HardwareUnavailableOrDisabled) |