mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
fix: Behavior when ask device credential #2283
This commit is contained in:
@@ -57,7 +57,7 @@ import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
|
|||||||
import com.kunzisoft.keepass.adapters.TagsAdapter
|
import com.kunzisoft.keepass.adapters.TagsAdapter
|
||||||
import com.kunzisoft.keepass.credentialprovider.SpecialMode
|
import com.kunzisoft.keepass.credentialprovider.SpecialMode
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationData
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationData
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.askUserVerification
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.checkUserVerification
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.isUserVerificationNeeded
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.isUserVerificationNeeded
|
||||||
import com.kunzisoft.keepass.credentialprovider.magikeyboard.MagikeyboardService
|
import com.kunzisoft.keepass.credentialprovider.magikeyboard.MagikeyboardService
|
||||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||||
@@ -331,17 +331,7 @@ class EntryActivity : DatabaseLockActivity() {
|
|||||||
mUserVerificationViewModel.onUserVerificationReceived()
|
mUserVerificationViewModel.onUserVerificationReceived()
|
||||||
}
|
}
|
||||||
is UserVerificationViewModel.UIState.OnUserVerificationSucceeded -> {
|
is UserVerificationViewModel.UIState.OnUserVerificationSucceeded -> {
|
||||||
uIState.dataToVerify.database?.let { database ->
|
editEntry(uIState.dataToVerify.database, uIState.dataToVerify.entryId)
|
||||||
uIState.dataToVerify.entryId?.let { entryId ->
|
|
||||||
EntryEditActivity.launch(
|
|
||||||
activity = this@EntryActivity,
|
|
||||||
database = database,
|
|
||||||
registrationType = EntryEditActivity.RegistrationType.UPDATE,
|
|
||||||
nodeId = entryId,
|
|
||||||
activityResultLauncher = mEntryActivityResultLauncher
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mUserVerificationViewModel.onUserVerificationReceived()
|
mUserVerificationViewModel.onUserVerificationReceived()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,15 +490,31 @@ class EntryActivity : DatabaseLockActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun editEntry(database: ContextualDatabase?, entryId: NodeId<*>?) {
|
||||||
|
database?.let { database ->
|
||||||
|
entryId?.let { entryId ->
|
||||||
|
EntryEditActivity.launch(
|
||||||
|
activity = this@EntryActivity,
|
||||||
|
database = database,
|
||||||
|
registrationType = EntryEditActivity.RegistrationType.UPDATE,
|
||||||
|
nodeId = entryId,
|
||||||
|
activityResultLauncher = mEntryActivityResultLauncher
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.menu_edit -> {
|
R.id.menu_edit -> {
|
||||||
askUserVerification(
|
if (mEntryViewModel.entryInfo?.isUserVerificationNeeded() == true) {
|
||||||
userVerificationViewModel = mUserVerificationViewModel,
|
checkUserVerification(
|
||||||
userVerificationCondition = mEntryViewModel.entryInfo
|
userVerificationViewModel = mUserVerificationViewModel,
|
||||||
?.isUserVerificationNeeded() == true,
|
dataToVerify = UserVerificationData(mDatabase, mEntryViewModel.mainEntryId)
|
||||||
dataToVerify = UserVerificationData(mDatabase, mEntryViewModel.mainEntryId)
|
)
|
||||||
)
|
} else {
|
||||||
|
editEntry(mDatabase, mEntryViewModel.mainEntryId)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.menu_restore_entry_history -> {
|
R.id.menu_restore_entry_history -> {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.retrieveSea
|
|||||||
import com.kunzisoft.keepass.credentialprovider.SpecialMode
|
import com.kunzisoft.keepass.credentialprovider.SpecialMode
|
||||||
import com.kunzisoft.keepass.credentialprovider.TypeMode
|
import com.kunzisoft.keepass.credentialprovider.TypeMode
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationData
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationData
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.askUserVerification
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.checkUserVerification
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.isUserVerificationNeeded
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.isUserVerificationNeeded
|
||||||
import com.kunzisoft.keepass.credentialprovider.magikeyboard.MagikeyboardService
|
import com.kunzisoft.keepass.credentialprovider.magikeyboard.MagikeyboardService
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.util.PasskeyHelper.buildPasskeyResponseAndSetResult
|
import com.kunzisoft.keepass.credentialprovider.passkey.util.PasskeyHelper.buildPasskeyResponseAndSetResult
|
||||||
@@ -584,17 +584,7 @@ class GroupActivity : DatabaseLockActivity(),
|
|||||||
mUserVerificationViewModel.onUserVerificationReceived()
|
mUserVerificationViewModel.onUserVerificationReceived()
|
||||||
}
|
}
|
||||||
is UserVerificationViewModel.UIState.OnUserVerificationSucceeded -> {
|
is UserVerificationViewModel.UIState.OnUserVerificationSucceeded -> {
|
||||||
uIState.dataToVerify.database?.let { database ->
|
editEntry(uIState.dataToVerify.database, uIState.dataToVerify.entryId)
|
||||||
uIState.dataToVerify.entryId?.let { entryId ->
|
|
||||||
EntryEditActivity.launch(
|
|
||||||
activity = this@GroupActivity,
|
|
||||||
database = database,
|
|
||||||
registrationType = EntryEditActivity.RegistrationType.UPDATE,
|
|
||||||
nodeId = entryId,
|
|
||||||
activityResultLauncher = mEntryActivityResultLauncher
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mUserVerificationViewModel.onUserVerificationReceived()
|
mUserVerificationViewModel.onUserVerificationReceived()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1047,6 +1037,20 @@ class GroupActivity : DatabaseLockActivity(),
|
|||||||
).containsSearchInfo(searchInfo)
|
).containsSearchInfo(searchInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun editEntry(database: ContextualDatabase?, entryId: NodeId<*>?) {
|
||||||
|
database?.let {
|
||||||
|
entryId?.let {
|
||||||
|
EntryEditActivity.launch(
|
||||||
|
activity = this@GroupActivity,
|
||||||
|
database = database,
|
||||||
|
registrationType = EntryEditActivity.RegistrationType.UPDATE,
|
||||||
|
nodeId = entryId,
|
||||||
|
activityResultLauncher = mEntryActivityResultLauncher
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun finishNodeAction() {
|
private fun finishNodeAction() {
|
||||||
actionNodeMode?.finish()
|
actionNodeMode?.finish()
|
||||||
}
|
}
|
||||||
@@ -1096,12 +1100,14 @@ class GroupActivity : DatabaseLockActivity(),
|
|||||||
launchDialogForGroupUpdate(node as Group)
|
launchDialogForGroupUpdate(node as Group)
|
||||||
}
|
}
|
||||||
Type.ENTRY -> {
|
Type.ENTRY -> {
|
||||||
askUserVerification(
|
if ((node as Entry).getEntryInfo(database).isUserVerificationNeeded()) {
|
||||||
userVerificationViewModel = mUserVerificationViewModel,
|
checkUserVerification(
|
||||||
userVerificationCondition = (node as Entry).getEntryInfo(database)
|
userVerificationViewModel = mUserVerificationViewModel,
|
||||||
.isUserVerificationNeeded(),
|
dataToVerify = UserVerificationData(database, node.nodeId)
|
||||||
dataToVerify = UserVerificationData(database,node.nodeId)
|
)
|
||||||
)
|
} else {
|
||||||
|
editEntry(database, node.nodeId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -75,9 +75,14 @@ class UserVerificationHelper {
|
|||||||
/**
|
/**
|
||||||
* Get the User Verification from the intent
|
* Get the User Verification from the intent
|
||||||
*/
|
*/
|
||||||
fun Intent.getUserVerificationCondition(): Boolean {
|
fun Intent.isUserVerificationNeeded(userVerificationPreferred: Boolean): Boolean {
|
||||||
return (getEnumExtra<UserVerificationRequirement>(EXTRA_USER_VERIFICATION)
|
val userVerification: UserVerificationRequirement =
|
||||||
?: UserVerificationRequirement.PREFERRED) == UserVerificationRequirement.REQUIRED
|
getEnumExtra<UserVerificationRequirement>(EXTRA_USER_VERIFICATION)
|
||||||
|
?: UserVerificationRequirement.PREFERRED
|
||||||
|
return (userVerification == UserVerificationRequirement.REQUIRED
|
||||||
|
|| (userVerificationPreferred
|
||||||
|
&& userVerification == UserVerificationRequirement.PREFERRED)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,67 +92,66 @@ class UserVerificationHelper {
|
|||||||
return this.passkey != null
|
return this.passkey != null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun FragmentActivity.checkUserVerification(
|
||||||
* Ask the user for verification
|
|
||||||
* Ask for the biometric if defined on the device
|
|
||||||
* Ask for the database credential otherwise
|
|
||||||
*/
|
|
||||||
fun FragmentActivity.askUserVerification(
|
|
||||||
userVerificationViewModel: UserVerificationViewModel,
|
userVerificationViewModel: UserVerificationViewModel,
|
||||||
userVerificationCondition: Boolean,
|
|
||||||
dataToVerify: UserVerificationData
|
dataToVerify: UserVerificationData
|
||||||
) {
|
) {
|
||||||
if (isAuthenticatorsAllowed() && userVerificationCondition) {
|
if (isAuthenticatorsAllowed()) {
|
||||||
// Important to check the nullable database here
|
showUserVerificationDeviceCredential(userVerificationViewModel, dataToVerify)
|
||||||
dataToVerify.database?.let {
|
|
||||||
BiometricPrompt(
|
|
||||||
this, ContextCompat.getMainExecutor(this),
|
|
||||||
object : BiometricPrompt.AuthenticationCallback() {
|
|
||||||
override fun onAuthenticationError(
|
|
||||||
errorCode: Int,
|
|
||||||
errString: CharSequence
|
|
||||||
) {
|
|
||||||
super.onAuthenticationError(errorCode, errString)
|
|
||||||
when (errorCode) {
|
|
||||||
BiometricPrompt.ERROR_CANCELED,
|
|
||||||
BiometricPrompt.ERROR_NEGATIVE_BUTTON,
|
|
||||||
BiometricPrompt.ERROR_USER_CANCELED -> {
|
|
||||||
// No operation
|
|
||||||
Log.i("UserVerification", "$errString")
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
toastError(SecurityException("Authentication error: $errString"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
userVerificationViewModel.onUserVerificationFailed(dataToVerify)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAuthenticationSucceeded(
|
|
||||||
result: BiometricPrompt.AuthenticationResult
|
|
||||||
) {
|
|
||||||
super.onAuthenticationSucceeded(result)
|
|
||||||
userVerificationViewModel.onUserVerificationSucceeded(dataToVerify)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAuthenticationFailed() {
|
|
||||||
super.onAuthenticationFailed()
|
|
||||||
toastError(SecurityException(getString(R.string.device_unlock_not_recognized)))
|
|
||||||
userVerificationViewModel.onUserVerificationFailed(dataToVerify)
|
|
||||||
}
|
|
||||||
}).authenticate(
|
|
||||||
BiometricPrompt.PromptInfo.Builder()
|
|
||||||
.setTitle(getString(R.string.user_verification_required))
|
|
||||||
.setAllowedAuthenticators(ALLOWED_AUTHENTICATORS)
|
|
||||||
.setConfirmationRequired(false)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
userVerificationViewModel.onUserVerificationSucceeded(dataToVerify)
|
showUserVerificationMessage {
|
||||||
|
userVerificationViewModel.onUserVerificationFailed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun FragmentActivity.showUserVerificationDeviceCredential(
|
||||||
|
userVerificationViewModel: UserVerificationViewModel,
|
||||||
|
dataToVerify: UserVerificationData
|
||||||
|
) {
|
||||||
|
BiometricPrompt(
|
||||||
|
this, ContextCompat.getMainExecutor(this),
|
||||||
|
object : BiometricPrompt.AuthenticationCallback() {
|
||||||
|
override fun onAuthenticationError(
|
||||||
|
errorCode: Int,
|
||||||
|
errString: CharSequence
|
||||||
|
) {
|
||||||
|
super.onAuthenticationError(errorCode, errString)
|
||||||
|
when (errorCode) {
|
||||||
|
BiometricPrompt.ERROR_CANCELED,
|
||||||
|
BiometricPrompt.ERROR_NEGATIVE_BUTTON,
|
||||||
|
BiometricPrompt.ERROR_USER_CANCELED -> {
|
||||||
|
// No operation
|
||||||
|
Log.i("UserVerification", "$errString")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
toastError(SecurityException("Authentication error: $errString"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
userVerificationViewModel.onUserVerificationFailed(dataToVerify)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationSucceeded(
|
||||||
|
result: BiometricPrompt.AuthenticationResult
|
||||||
|
) {
|
||||||
|
super.onAuthenticationSucceeded(result)
|
||||||
|
userVerificationViewModel.onUserVerificationSucceeded(dataToVerify)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationFailed() {
|
||||||
|
super.onAuthenticationFailed()
|
||||||
|
toastError(SecurityException(getString(R.string.device_unlock_not_recognized)))
|
||||||
|
userVerificationViewModel.onUserVerificationFailed(dataToVerify)
|
||||||
|
}
|
||||||
|
}).authenticate(
|
||||||
|
BiometricPrompt.PromptInfo.Builder()
|
||||||
|
.setTitle(getString(R.string.user_verification_required))
|
||||||
|
.setAllowedAuthenticators(ALLOWED_AUTHENTICATORS)
|
||||||
|
.setConfirmationRequired(false)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun FragmentActivity.showUserVerificationMessage(
|
fun FragmentActivity.showUserVerificationMessage(
|
||||||
onActionPerformed: () -> Unit
|
onActionPerformed: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -47,11 +47,9 @@ import com.kunzisoft.keepass.credentialprovider.SpecialMode
|
|||||||
import com.kunzisoft.keepass.credentialprovider.TypeMode
|
import com.kunzisoft.keepass.credentialprovider.TypeMode
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationData
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationData
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.addUserVerification
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.addUserVerification
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.askUserVerification
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.checkUserVerification
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.getUserVerificationCondition
|
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.getUserVerifiedWithAuth
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.getUserVerifiedWithAuth
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.isAuthenticatorsAllowed
|
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.isUserVerificationNeeded
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.showUserVerificationMessage
|
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.AndroidPrivilegedApp
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.AndroidPrivilegedApp
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.UserVerificationRequirement
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.UserVerificationRequirement
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.util.PasskeyHelper.addAppOrigin
|
import com.kunzisoft.keepass.credentialprovider.passkey.util.PasskeyHelper.addAppOrigin
|
||||||
@@ -63,6 +61,7 @@ import com.kunzisoft.keepass.model.AppOrigin
|
|||||||
import com.kunzisoft.keepass.model.SearchInfo
|
import com.kunzisoft.keepass.model.SearchInfo
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CHECK_CREDENTIAL_TASK
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CHECK_CREDENTIAL_TASK
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK
|
||||||
|
import com.kunzisoft.keepass.settings.PreferencesUtil.isPasskeyUserVerificationPreferred
|
||||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||||
import com.kunzisoft.keepass.utils.AppUtil.randomRequestCode
|
import com.kunzisoft.keepass.utils.AppUtil.randomRequestCode
|
||||||
import com.kunzisoft.keepass.view.toastError
|
import com.kunzisoft.keepass.view.toastError
|
||||||
@@ -202,16 +201,20 @@ class PasskeyLauncherActivity : DatabaseLockActivity() {
|
|||||||
override fun onUnknownDatabaseRetrieved(database: ContextualDatabase?) {
|
override fun onUnknownDatabaseRetrieved(database: ContextualDatabase?) {
|
||||||
super.onUnknownDatabaseRetrieved(database)
|
super.onUnknownDatabaseRetrieved(database)
|
||||||
// To manage https://github.com/Kunzisoft/KeePassDX/issues/2283
|
// To manage https://github.com/Kunzisoft/KeePassDX/issues/2283
|
||||||
if (isAuthenticatorsAllowed()) {
|
val userVerificationNeeded = intent.isUserVerificationNeeded(
|
||||||
askUserVerification(
|
userVerificationPreferred = isPasskeyUserVerificationPreferred(this)
|
||||||
|
) && intent.getUserVerifiedWithAuth().not()
|
||||||
|
if (userVerificationNeeded) {
|
||||||
|
checkUserVerification(
|
||||||
userVerificationViewModel = userVerificationViewModel,
|
userVerificationViewModel = userVerificationViewModel,
|
||||||
userVerificationCondition = intent.getUserVerificationCondition(),
|
|
||||||
dataToVerify = UserVerificationData(database)
|
dataToVerify = UserVerificationData(database)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
showUserVerificationMessage {
|
passkeyLauncherViewModel.launchActionIfNeeded(
|
||||||
userVerificationViewModel.onUserVerificationFailed()
|
intent = intent,
|
||||||
}
|
specialMode = mSpecialMode,
|
||||||
|
database = database
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,8 +150,7 @@ class PasskeyProviderService : CredentialProviderService() {
|
|||||||
val credentialIdList = publicKeyCredentialRequestOptions.allowCredentials
|
val credentialIdList = publicKeyCredentialRequestOptions.allowCredentials
|
||||||
.map { b64Encode(it.id) }
|
.map { b64Encode(it.id) }
|
||||||
val searchInfo = buildPasskeySearchInfo(relyingPartyId, credentialIdList)
|
val searchInfo = buildPasskeySearchInfo(relyingPartyId, credentialIdList)
|
||||||
// TODO remove
|
val userVerification = publicKeyCredentialRequestOptions.userVerification
|
||||||
val userVerification = UserVerificationRequirement.REQUIRED//publicKeyCredentialRequestOptions.userVerification
|
|
||||||
Log.d(TAG, "Build passkey search for UV $userVerification, " +
|
Log.d(TAG, "Build passkey search for UV $userVerification, " +
|
||||||
"RP $relyingPartyId and Credential IDs $credentialIdList")
|
"RP $relyingPartyId and Credential IDs $credentialIdList")
|
||||||
SearchHelper.checkAutoSearchInfo(
|
SearchHelper.checkAutoSearchInfo(
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.retrieveNod
|
|||||||
import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.retrieveSearchInfo
|
import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.retrieveSearchInfo
|
||||||
import com.kunzisoft.keepass.credentialprovider.SpecialMode
|
import com.kunzisoft.keepass.credentialprovider.SpecialMode
|
||||||
import com.kunzisoft.keepass.credentialprovider.TypeMode
|
import com.kunzisoft.keepass.credentialprovider.TypeMode
|
||||||
import com.kunzisoft.keepass.credentialprovider.UserVerificationHelper.Companion.getUserVerificationCondition
|
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.AndroidPrivilegedApp
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.AndroidPrivilegedApp
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialCreationParameters
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialCreationParameters
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialUsageParameters
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialUsageParameters
|
||||||
@@ -159,7 +158,7 @@ class PasskeyLauncherViewModel(application: Application): CredentialLauncherView
|
|||||||
database: ContextualDatabase?
|
database: ContextualDatabase?
|
||||||
) {
|
) {
|
||||||
this.mUserVerified = userVerified
|
this.mUserVerified = userVerified
|
||||||
super.launchActionIfNeeded(intent, specialMode, database)
|
launchActionIfNeeded(intent, specialMode, database)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun launchActionIfNeeded(
|
override fun launchActionIfNeeded(
|
||||||
@@ -167,15 +166,9 @@ class PasskeyLauncherViewModel(application: Application): CredentialLauncherView
|
|||||||
specialMode: SpecialMode,
|
specialMode: SpecialMode,
|
||||||
database: ContextualDatabase?
|
database: ContextualDatabase?
|
||||||
) {
|
) {
|
||||||
if (intent.getUserVerificationCondition()) {
|
// Launch with database when a nodeId is present
|
||||||
if (database != null) {
|
if ((database != null && database.loaded) || intent.retrieveNodeId() == null) {
|
||||||
onDatabaseRetrieved(database)
|
super.launchActionIfNeeded(intent, specialMode, database)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Launch with database when a nodeId is present
|
|
||||||
if ((database != null && database.loaded) || intent.retrieveNodeId() == null) {
|
|
||||||
super.launchActionIfNeeded(intent, specialMode, database)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -690,6 +690,12 @@ object PreferencesUtil {
|
|||||||
context.resources.getBoolean(R.bool.passkeys_close_database_default))
|
context.resources.getBoolean(R.bool.passkeys_close_database_default))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isPasskeyUserVerificationPreferred(context: Context): Boolean {
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
return prefs.getBoolean(context.getString(R.string.passkeys_user_verification_preferred_key),
|
||||||
|
context.resources.getBoolean(R.bool.passkeys_user_verification_preferred_default))
|
||||||
|
}
|
||||||
|
|
||||||
fun isPasskeyBackupEligibilityEnable(context: Context): Boolean {
|
fun isPasskeyBackupEligibilityEnable(context: Context): Boolean {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
return prefs.getBoolean(context.getString(R.string.passkeys_backup_eligibility_key),
|
return prefs.getBoolean(context.getString(R.string.passkeys_backup_eligibility_key),
|
||||||
|
|||||||
@@ -139,6 +139,8 @@
|
|||||||
<string name="passkeys_privileged_apps_key" translatable="false">passkeys_privileged_apps_key</string>
|
<string name="passkeys_privileged_apps_key" translatable="false">passkeys_privileged_apps_key</string>
|
||||||
<string name="passkeys_auto_select_key" translatable="false">passkeys_auto_select_key</string>
|
<string name="passkeys_auto_select_key" translatable="false">passkeys_auto_select_key</string>
|
||||||
<bool name="passkeys_auto_select_default" translatable="false">true</bool>
|
<bool name="passkeys_auto_select_default" translatable="false">true</bool>
|
||||||
|
<string name="passkeys_user_verification_preferred_key" translatable="false">passkeys_user_verification_preferred_key</string>
|
||||||
|
<bool name="passkeys_user_verification_preferred_default" translatable="false">false</bool>
|
||||||
<string name="passkeys_backup_eligibility_key" translatable="false">passkeys_backup_eligibility_key</string>
|
<string name="passkeys_backup_eligibility_key" translatable="false">passkeys_backup_eligibility_key</string>
|
||||||
<bool name="passkeys_backup_eligibility_default" translatable="false">true</bool>
|
<bool name="passkeys_backup_eligibility_default" translatable="false">true</bool>
|
||||||
<string name="passkeys_backup_state_key" translatable="false">passkeys_backup_state_key</string>
|
<string name="passkeys_backup_state_key" translatable="false">passkeys_backup_state_key</string>
|
||||||
|
|||||||
@@ -434,6 +434,8 @@
|
|||||||
<string name="passkeys_missing_signature_app_ask_question">Add app signature to passkey entry?</string>
|
<string name="passkeys_missing_signature_app_ask_question">Add app signature to passkey entry?</string>
|
||||||
<string name="passkeys_auto_select_title">Auto select</string>
|
<string name="passkeys_auto_select_title">Auto select</string>
|
||||||
<string name="passkeys_auto_select_summary">Auto select if only one entry and the database is open, only if the requesting app is compatible</string>
|
<string name="passkeys_auto_select_summary">Auto select if only one entry and the database is open, only if the requesting app is compatible</string>
|
||||||
|
<string name="passkeys_user_verification_preferred_title">Preferred User Verification</string>
|
||||||
|
<string name="passkeys_user_verification_preferred_summary">Perform a user verification to access sensitive data when the relying party requests \"preferred\".</string>
|
||||||
<string name="passkeys_backup_eligibility_title">Backup Eligibility</string>
|
<string name="passkeys_backup_eligibility_title">Backup Eligibility</string>
|
||||||
<string name="passkeys_backup_eligibility_summary">Determine at creation time whether the public key credential source is allowed to be backed up</string>
|
<string name="passkeys_backup_eligibility_summary">Determine at creation time whether the public key credential source is allowed to be backed up</string>
|
||||||
<string name="passkeys_backup_state_title">Backup State</string>
|
<string name="passkeys_backup_state_title">Backup State</string>
|
||||||
|
|||||||
@@ -37,6 +37,11 @@
|
|||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:title="@string/database">
|
android:title="@string/database">
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:key="@string/passkeys_user_verification_preferred_key"
|
||||||
|
android:title="@string/passkeys_user_verification_preferred_title"
|
||||||
|
android:summary="@string/passkeys_user_verification_preferred_summary"
|
||||||
|
android:defaultValue="@bool/passkeys_user_verification_preferred_default"/>
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
android:key="@string/passkeys_backup_eligibility_key"
|
android:key="@string/passkeys_backup_eligibility_key"
|
||||||
android:title="@string/passkeys_backup_eligibility_title"
|
android:title="@string/passkeys_backup_eligibility_title"
|
||||||
|
|||||||
Reference in New Issue
Block a user