fix: correctly use biometrics result in passphrase cache flow
This commit is contained in:
parent
dfe4b14b4c
commit
fe7aee24d4
2 changed files with 57 additions and 31 deletions
|
@ -18,6 +18,7 @@ import app.passwordstore.data.passfile.PasswordEntry
|
|||
import app.passwordstore.ui.crypto.BasePGPActivity
|
||||
import app.passwordstore.ui.crypto.PasswordDialog
|
||||
import app.passwordstore.util.auth.BiometricAuthenticator
|
||||
import app.passwordstore.util.auth.BiometricAuthenticator.Result
|
||||
import app.passwordstore.util.autofill.AutofillPreferences
|
||||
import app.passwordstore.util.autofill.AutofillResponseBuilder
|
||||
import app.passwordstore.util.autofill.DirectoryStructure
|
||||
|
@ -70,7 +71,6 @@ class AutofillDecryptActivity : BasePGPActivity() {
|
|||
directoryStructure = AutofillPreferences.directoryStructure(this)
|
||||
logcat { action.toString() }
|
||||
requireKeysExist {
|
||||
val gpgIdentifiers = getPGPIdentifiers("") ?: return@requireKeysExist
|
||||
if (
|
||||
features.isEnabled(EnablePGPPassphraseCache) && BiometricAuthenticator.canAuthenticate(this)
|
||||
) {
|
||||
|
@ -78,25 +78,42 @@ class AutofillDecryptActivity : BasePGPActivity() {
|
|||
this,
|
||||
R.string.biometric_prompt_title_gpg_passphrase_cache,
|
||||
) { authResult ->
|
||||
if (authResult is BiometricAuthenticator.Result.Success) {
|
||||
lifecycleScope.launch {
|
||||
val cachedPassphrase =
|
||||
passphraseCache.retrieveCachedPassphrase(
|
||||
this@AutofillDecryptActivity,
|
||||
gpgIdentifiers.first()
|
||||
)
|
||||
if (cachedPassphrase != null) {
|
||||
decrypt(File(filePath), clientState, action, cachedPassphrase)
|
||||
} else {
|
||||
askPassphrase(filePath, clientState, action)
|
||||
}
|
||||
}
|
||||
decrypt(filePath, clientState, action, authResult)
|
||||
}
|
||||
} else {
|
||||
decrypt(filePath, clientState, action, Result.Cancelled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun decrypt(
|
||||
filePath: String,
|
||||
clientState: Bundle,
|
||||
action: AutofillAction,
|
||||
authResult: Result,
|
||||
) {
|
||||
val gpgIdentifiers = getPGPIdentifiers("") ?: return
|
||||
lifecycleScope.launch(dispatcherProvider.main()) {
|
||||
when (authResult) {
|
||||
// Internally handled by the prompt dialog
|
||||
is Result.Retry -> {}
|
||||
// If the dialog is dismissed for any reason, prompt for passphrase
|
||||
is Result.Cancelled,
|
||||
is Result.Failure,
|
||||
is Result.HardwareUnavailableOrDisabled -> askPassphrase(filePath, clientState, action)
|
||||
//
|
||||
is Result.Success -> {
|
||||
val cachedPassphrase =
|
||||
passphraseCache.retrieveCachedPassphrase(
|
||||
this@AutofillDecryptActivity,
|
||||
gpgIdentifiers.first()
|
||||
)
|
||||
if (cachedPassphrase != null) {
|
||||
decryptWithPassphrase(File(filePath), clientState, action, cachedPassphrase)
|
||||
} else {
|
||||
askPassphrase(filePath, clientState, action)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
askPassphrase(filePath, clientState, action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +124,7 @@ class AutofillDecryptActivity : BasePGPActivity() {
|
|||
withContext(dispatcherProvider.main()) {
|
||||
dialog.password.collectLatest { value ->
|
||||
if (value != null) {
|
||||
decrypt(File(filePath), clientState, action, value)
|
||||
decryptWithPassphrase(File(filePath), clientState, action, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +132,7 @@ class AutofillDecryptActivity : BasePGPActivity() {
|
|||
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
|
||||
}
|
||||
|
||||
private suspend fun decrypt(
|
||||
private suspend fun decryptWithPassphrase(
|
||||
filePath: File,
|
||||
clientState: Bundle,
|
||||
action: AutofillAction,
|
||||
|
|
|
@ -18,6 +18,7 @@ import app.passwordstore.data.password.FieldItem
|
|||
import app.passwordstore.databinding.DecryptLayoutBinding
|
||||
import app.passwordstore.ui.adapters.FieldItemAdapter
|
||||
import app.passwordstore.util.auth.BiometricAuthenticator
|
||||
import app.passwordstore.util.auth.BiometricAuthenticator.Result
|
||||
import app.passwordstore.util.extensions.getString
|
||||
import app.passwordstore.util.extensions.unsafeLazy
|
||||
import app.passwordstore.util.extensions.viewBinding
|
||||
|
@ -77,7 +78,7 @@ class DecryptActivity : BasePGPActivity() {
|
|||
requireKeysExist { decrypt(isError = false, authResult) }
|
||||
}
|
||||
} else {
|
||||
requireKeysExist { decrypt(isError = false, BiometricAuthenticator.Result.Cancelled) }
|
||||
requireKeysExist { decrypt(isError = false, Result.Cancelled) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,19 +150,27 @@ class DecryptActivity : BasePGPActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
private fun decrypt(isError: Boolean, authResult: BiometricAuthenticator.Result) {
|
||||
private fun decrypt(isError: Boolean, authResult: Result) {
|
||||
val gpgIdentifiers = getPGPIdentifiers("") ?: return
|
||||
lifecycleScope.launch(dispatcherProvider.main()) {
|
||||
if (authResult is BiometricAuthenticator.Result.Success) {
|
||||
val cachedPassphrase =
|
||||
passphraseCache.retrieveCachedPassphrase(this@DecryptActivity, gpgIdentifiers.first())
|
||||
if (cachedPassphrase != null) {
|
||||
decryptWithCachedPassphrase(cachedPassphrase, gpgIdentifiers, authResult)
|
||||
} else {
|
||||
when (authResult) {
|
||||
// Internally handled by the prompt dialog
|
||||
is Result.Retry -> {}
|
||||
// If the dialog is dismissed for any reason, prompt for passphrase
|
||||
is Result.Cancelled,
|
||||
is Result.Failure,
|
||||
is Result.HardwareUnavailableOrDisabled ->
|
||||
askPassphrase(isError, gpgIdentifiers, authResult)
|
||||
//
|
||||
is Result.Success -> {
|
||||
val cachedPassphrase =
|
||||
passphraseCache.retrieveCachedPassphrase(this@DecryptActivity, gpgIdentifiers.first())
|
||||
if (cachedPassphrase != null) {
|
||||
decryptWithCachedPassphrase(cachedPassphrase, gpgIdentifiers, authResult)
|
||||
} else {
|
||||
askPassphrase(isError, gpgIdentifiers, authResult)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
askPassphrase(isError, gpgIdentifiers, authResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +178,7 @@ class DecryptActivity : BasePGPActivity() {
|
|||
private fun askPassphrase(
|
||||
isError: Boolean,
|
||||
gpgIdentifiers: List<PGPIdentifier>,
|
||||
authResult: BiometricAuthenticator.Result,
|
||||
authResult: Result,
|
||||
) {
|
||||
if (retries < MAX_RETRIES) {
|
||||
retries += 1
|
||||
|
@ -189,7 +198,7 @@ class DecryptActivity : BasePGPActivity() {
|
|||
passwordEntry = entry
|
||||
createPasswordUI(entry)
|
||||
startAutoDismissTimer()
|
||||
if (authResult is BiometricAuthenticator.Result.Success) {
|
||||
if (authResult is Result.Success) {
|
||||
passphraseCache.cachePassphrase(this@DecryptActivity, gpgIdentifiers.first(), value)
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +216,7 @@ class DecryptActivity : BasePGPActivity() {
|
|||
private suspend fun decryptWithCachedPassphrase(
|
||||
passphrase: String,
|
||||
identifiers: List<PGPIdentifier>,
|
||||
authResult: BiometricAuthenticator.Result,
|
||||
authResult: Result,
|
||||
) {
|
||||
when (val result = decryptWithPassphrase(passphrase, identifiers)) {
|
||||
is Ok -> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue