diff options
| author | Harsh Shandilya <msfjarvis@gmail.com> | 2020-04-24 15:00:33 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-24 15:00:33 +0530 |
| commit | 73695e2493af46c2375bb7678cb879d33a8aed4f (patch) | |
| tree | 218cdd48c75e64bd7945b46622ef15ea161d72c0 /app/src/main/java/com/zeapo/pwdstore/utils | |
| parent | bee20ac44a6b03082ee85cb52db4d8f32e2dd899 (diff) | |
| download | HardenedPass-73695e2493af46c2375bb7678cb879d33a8aed4f.tar.gz HardenedPass-73695e2493af46c2375bb7678cb879d33a8aed4f.zip | |
auth: redo implementation with a cleaner and simpler API surface (#741)
Diffstat (limited to 'app/src/main/java/com/zeapo/pwdstore/utils')
3 files changed, 74 insertions, 89 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/BiometricAuthenticator.kt b/app/src/main/java/com/zeapo/pwdstore/utils/BiometricAuthenticator.kt new file mode 100644 index 00000000..36d1f8f4 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/utils/BiometricAuthenticator.kt @@ -0,0 +1,74 @@ +/* + * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ +package com.zeapo.pwdstore.utils + +import android.app.KeyguardManager +import android.os.Handler +import androidx.annotation.StringRes +import androidx.biometric.BiometricConstants +import androidx.biometric.BiometricManager +import androidx.biometric.BiometricPrompt +import androidx.core.content.getSystemService +import androidx.fragment.app.FragmentActivity +import com.github.ajalt.timberkt.Timber.tag +import com.github.ajalt.timberkt.d +import com.zeapo.pwdstore.R + +object BiometricAuthenticator { + private const val TAG = "BiometricAuthenticator" + private val handler = Handler() + + sealed class Result { + data class Success(val cryptoObject: BiometricPrompt.CryptoObject?) : Result() + data class Failure(val code: Int?, val message: CharSequence) : Result() + object HardwareUnavailableOrDisabled : Result() + object Cancelled : Result() + } + + fun authenticate( + activity: FragmentActivity, + @StringRes dialogTitleRes: Int = R.string.biometric_prompt_title, + callback: (Result) -> Unit + ) { + val authCallback = object : BiometricPrompt.AuthenticationCallback() { + override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { + super.onAuthenticationError(errorCode, errString) + tag(TAG).d { "BiometricAuthentication error: errorCode=$errorCode, msg=$errString" } + callback(when (errorCode) { + BiometricConstants.ERROR_CANCELED, BiometricConstants.ERROR_USER_CANCELED, + BiometricConstants.ERROR_NEGATIVE_BUTTON -> { + Result.Cancelled + } + BiometricConstants.ERROR_HW_NOT_PRESENT, BiometricConstants.ERROR_HW_UNAVAILABLE, + BiometricConstants.ERROR_NO_BIOMETRICS, BiometricConstants.ERROR_NO_DEVICE_CREDENTIAL -> { + Result.HardwareUnavailableOrDisabled + } + else -> Result.Failure(errorCode, activity.getString(R.string.biometric_auth_error_reason, errString)) + }) + } + + override fun onAuthenticationFailed() { + super.onAuthenticationFailed() + callback(Result.Failure(null, activity.getString(R.string.biometric_auth_error))) + } + + override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { + super.onAuthenticationSucceeded(result) + callback(Result.Success(result.cryptoObject)) + } + } + val biometricPrompt = BiometricPrompt(activity, { handler.post(it) }, authCallback) + val promptInfo = BiometricPrompt.PromptInfo.Builder() + .setTitle(activity.getString(dialogTitleRes)) + .setDeviceCredentialAllowed(true) + .build() + if (BiometricManager.from(activity).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS || + activity.getSystemService<KeyguardManager>()?.isDeviceSecure == true) { + biometricPrompt.authenticate(promptInfo) + } else { + callback(Result.HardwareUnavailableOrDisabled) + } + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/auth/AuthenticationResult.kt b/app/src/main/java/com/zeapo/pwdstore/utils/auth/AuthenticationResult.kt deleted file mode 100644 index 6bde6360..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/utils/auth/AuthenticationResult.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.utils.auth - -import androidx.biometric.BiometricPrompt - -internal sealed class AuthenticationResult { - internal data class Success(val cryptoObject: BiometricPrompt.CryptoObject?) : - AuthenticationResult() - - internal data class RecoverableError(val code: Int, val message: CharSequence) : - AuthenticationResult() - - internal data class UnrecoverableError(val code: Int, val message: CharSequence) : - AuthenticationResult() - - internal object Failure : AuthenticationResult() - internal object Cancelled : AuthenticationResult() -} diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/auth/Authenticator.kt b/app/src/main/java/com/zeapo/pwdstore/utils/auth/Authenticator.kt deleted file mode 100644 index 34fc9455..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/utils/auth/Authenticator.kt +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.utils.auth - -import android.os.Handler -import androidx.biometric.BiometricManager -import androidx.biometric.BiometricPrompt -import androidx.fragment.app.FragmentActivity -import com.github.ajalt.timberkt.Timber.tag -import com.github.ajalt.timberkt.d -import com.zeapo.pwdstore.R - -internal class Authenticator( - private val fragmentActivity: FragmentActivity, - private val callback: (AuthenticationResult) -> Unit -) { - private val handler = Handler() - private val biometricManager = BiometricManager.from(fragmentActivity) - - private val authCallback = object : BiometricPrompt.AuthenticationCallback() { - - override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { - super.onAuthenticationError(errorCode, errString) - tag(TAG).d { "Error: $errorCode: $errString" } - callback(AuthenticationResult.UnrecoverableError(errorCode, errString)) - } - - override fun onAuthenticationFailed() { - super.onAuthenticationFailed() - tag(TAG).d { "Failed" } - callback(AuthenticationResult.Failure) - } - - override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { - super.onAuthenticationSucceeded(result) - tag(TAG).d { "Success" } - callback(AuthenticationResult.Success(result.cryptoObject)) - } - } - - private val biometricPrompt = BiometricPrompt( - fragmentActivity, - { runnable -> handler.post(runnable) }, - authCallback - ) - - private val promptInfo = BiometricPrompt.PromptInfo.Builder() - .setTitle(fragmentActivity.getString(R.string.biometric_prompt_title)) - .setDeviceCredentialAllowed(true) - .build() - - fun authenticate() { - if (biometricManager.canAuthenticate() != BiometricManager.BIOMETRIC_SUCCESS) { - callback(AuthenticationResult.UnrecoverableError( - 0, - fragmentActivity.getString(R.string.biometric_prompt_no_hardware) - )) - } else { - biometricPrompt.authenticate(promptInfo) - } - } - - companion object { - private const val TAG = "Authenticator" - } -} |
