aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarsh Shandilya <msfjarvis@gmail.com>2020-04-24 15:00:33 +0530
committerGitHub <noreply@github.com>2020-04-24 15:00:33 +0530
commit73695e2493af46c2375bb7678cb879d33a8aed4f (patch)
tree218cdd48c75e64bd7945b46622ef15ea161d72c0
parentbee20ac44a6b03082ee85cb52db4d8f32e2dd899 (diff)
auth: redo implementation with a cleaner and simpler API surface (#741)
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt18
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/UserPreference.kt9
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/utils/BiometricAuthenticator.kt74
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/utils/auth/AuthenticationResult.kt21
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/utils/auth/Authenticator.kt68
-rw-r--r--app/src/main/res/values-ru/strings.xml3
-rw-r--r--app/src/main/res/values/strings.xml5
7 files changed, 90 insertions, 108 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt b/app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt
index 7db8cd48..b5902199 100644
--- a/app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt
@@ -8,10 +8,10 @@ import android.content.Intent
import android.os.Bundle
import android.os.Handler
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.zeapo.pwdstore.crypto.PgpActivity
-import com.zeapo.pwdstore.utils.auth.AuthenticationResult
-import com.zeapo.pwdstore.utils.auth.Authenticator
+import com.zeapo.pwdstore.utils.BiometricAuthenticator
class LaunchActivity : AppCompatActivity() {
@@ -19,18 +19,20 @@ class LaunchActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
if (prefs.getBoolean("biometric_auth", false)) {
- Authenticator(this) {
+ BiometricAuthenticator.authenticate(this) {
when (it) {
- is AuthenticationResult.Success -> {
+ is BiometricAuthenticator.Result.Success -> {
startTargetActivity(false)
}
- is AuthenticationResult.UnrecoverableError -> {
- finish()
+ is BiometricAuthenticator.Result.HardwareUnavailableOrDisabled -> {
+ prefs.edit { remove("biometric_auth") }
+ startTargetActivity(false)
}
- else -> {
+ is BiometricAuthenticator.Result.Failure, BiometricAuthenticator.Result.Cancelled -> {
+ finish()
}
}
- }.authenticate()
+ }
} else {
startTargetActivity(true)
}
diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
index 32d1e87a..a9629c6c 100644
--- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
@@ -46,9 +46,8 @@ import com.zeapo.pwdstore.git.GitServerConfigActivity
import com.zeapo.pwdstore.pwgenxkpwd.XkpwdDictionary
import com.zeapo.pwdstore.sshkeygen.ShowSshKeyFragment
import com.zeapo.pwdstore.sshkeygen.SshKeyGenActivity
+import com.zeapo.pwdstore.utils.BiometricAuthenticator
import com.zeapo.pwdstore.utils.PasswordRepository
-import com.zeapo.pwdstore.utils.auth.AuthenticationResult
-import com.zeapo.pwdstore.utils.auth.Authenticator
import com.zeapo.pwdstore.utils.autofillManager
import com.zeapo.pwdstore.utils.getEncryptedPrefs
import java.io.File
@@ -297,9 +296,9 @@ class UserPreference : AppCompatActivity() {
isEnabled = false
sharedPreferences.edit {
val checked = isChecked
- Authenticator(requireActivity()) { result ->
+ BiometricAuthenticator.authenticate(requireActivity()) { result ->
when (result) {
- is AuthenticationResult.Success -> {
+ is BiometricAuthenticator.Result.Success -> {
// Apply the changes
putBoolean("biometric_auth", checked)
isEnabled = true
@@ -312,7 +311,7 @@ class UserPreference : AppCompatActivity() {
isEnabled = true
}
}
- }.authenticate()
+ }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
requireContext().getSystemService<ShortcutManager>()?.apply {
removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList())
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"
- }
-}
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 07c4dca7..9e192c1d 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -296,9 +296,6 @@
<string name="sdcard_root_warning_message">Вы выбрали корень вашей sd-карты для хранения. Это очень опасно и вы потеряете ваши данные, поскольку они будут в конечном итоге удалены</string>
<string name="git_abort_and_push_title">Прервать и записать изменения</string>
<string name="biometric_prompt_title">Запрос биометрии</string>
- <string name="biometric_prompt_retry">Повторить</string>
- <string name="biometric_prompt_cancelled">Аутентификация отменена</string>
- <string name="biometric_prompt_no_hardware">Биометрические сенсоры не обнаружены</string>
<string name="biometric_auth_title">Включить биометрическую аутентификацию</string>
<string name="biometric_auth_summary">Когда ключено, Password Store будет запрашивать ваш опечаток пальца при каждом запуске приложения</string>
<string name="biometric_auth_summary_error">Сенсор отпечатка пальца не доступен или отсутствует</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 33c0b103..37dbfef6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -326,9 +326,8 @@
<string name="sdcard_root_warning_message">You have selected the root of your sdcard for the store. This is extremely dangerous and you will lose your data as its content will, eventually, be deleted</string>
<string name="git_abort_and_push_title">Abort and Push</string>
<string name="biometric_prompt_title">Biometric Prompt</string>
- <string name="biometric_prompt_retry">Retry</string>
- <string name="biometric_prompt_cancelled">Authentication canceled</string>
- <string name="biometric_prompt_no_hardware">No Biometric hardware was found</string>
+ <string name="biometric_auth_error">Authentication failure</string>
+ <string name="biometric_auth_error_reason">Authentication failure: %s</string>
<string name="biometric_auth_title">Enable biometric authentication</string>
<string name="biometric_auth_summary">When enabled, Password Store will prompt you for your fingerprint when launching the app</string>
<string name="biometric_auth_summary_error">Fingerprint hardware not accessible or missing</string>