From cae27f63b366b5cef850a8faf14f7ba31370e0bd Mon Sep 17 00:00:00 2001 From: Yogesh Choudhary Paliyal Date: Sun, 15 Sep 2024 16:48:59 +0530 Subject: [PATCH] Disable biometric login after 24 hours of last password login (#971) * Disable biometric login after 24 hours of last password login Fixes #951 Add logic to disable biometric login if the user has not logged in via password in the last 24 hours. * **UserSettings.kt** - Add `lastPasswordLoginTime` attribute to track the last password login time. * **BiometricPrompt.kt** - Add logic to check `lastPasswordLoginTime` and disable biometric login if the last password login was more than 24 hours ago. - Add function `updateLastBiometricLoginTime` to update the last biometric login time. * **AuthScreen.kt** - Add logic to reset `lastPasswordLoginTime` when users log in via password. * **SharedPreferenceUtils.kt** - Add functions `updateLastBiometricLoginTime` and `updateLastPasswordLoginTime` to update the respective times in `UserSettings`. * **ButtonBar.kt** - Add logic to reset `lastPasswordLoginTime` when users log in via password. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/yogeshpaliyal/KeyPass/issues/951?shareId=XXXX-XXXX-XXXX-XXXX). * feat: fix changes * feat: cleanup --- .../keypass/ui/auth/components/ButtonBar.kt | 17 ++++++++++++++++- app/src/main/res/values/strings.xml | 1 + .../yogeshpaliyal/common/data/UserSettings.kt | 3 ++- .../common/utils/SharedPreferenceUtils.kt | 6 ++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/auth/components/ButtonBar.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/auth/components/ButtonBar.kt index cc54ed9e..665c3317 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/auth/components/ButtonBar.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/auth/components/ButtonBar.kt @@ -15,15 +15,19 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import com.yogeshpaliyal.common.utils.setKeyPassPassword +import com.yogeshpaliyal.common.utils.updateLastPasswordLoginTime import com.yogeshpaliyal.keypass.R import com.yogeshpaliyal.keypass.ui.nav.LocalUserSettings import com.yogeshpaliyal.keypass.ui.redux.KeyPassRedux import com.yogeshpaliyal.keypass.ui.redux.actions.Action import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction +import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction import com.yogeshpaliyal.keypass.ui.redux.states.AuthState import com.yogeshpaliyal.keypass.ui.redux.states.HomeState import kotlinx.coroutines.launch +import kotlin.time.DurationUnit +import kotlin.time.toDuration @Composable fun ButtonBar( @@ -48,7 +52,17 @@ fun ButtonBar( if (userSettings.isBiometricEnable && state is AuthState.Login) { OutlinedButton(onClick = { - setBiometricEnable(true) + val currentTime = System.currentTimeMillis() + val lastPasswordLoginTime = userSettings.lastPasswordLoginTime ?: -1 + if (lastPasswordLoginTime > 0 && (currentTime - lastPasswordLoginTime).toDuration( + DurationUnit.MILLISECONDS + ).inWholeHours < 24 + ) { + setBiometricEnable(true) + } else { + // User exceeds 24 hours before entering the password + dispatchAction(ToastAction(R.string.biometric_disabled_due_to_timeout)) + } }) { Text(text = stringResource(id = R.string.unlock_with_biometric)) } @@ -83,6 +97,7 @@ fun ButtonBar( coroutineScope.launch { val savedPassword = userSettings.keyPassPassword if (savedPassword == password) { + context.updateLastPasswordLoginTime(System.currentTimeMillis()) KeyPassRedux.getLastScreen()?.let { dispatchAction(GoBackAction) } ?: dispatchAction(NavigationAction(HomeState(), true)) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 989bdfb0..2271b3d6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -121,5 +121,6 @@ Invalid CSV File File not found (please try again) Enter password hint + Please login via password because you haven\'t used password in last 24 hours diff --git a/common/src/main/java/com/yogeshpaliyal/common/data/UserSettings.kt b/common/src/main/java/com/yogeshpaliyal/common/data/UserSettings.kt index ae6ecdb9..31f763a4 100644 --- a/common/src/main/java/com/yogeshpaliyal/common/data/UserSettings.kt +++ b/common/src/main/java/com/yogeshpaliyal/common/data/UserSettings.kt @@ -22,7 +22,8 @@ data class UserSettings( val lastAppVersion: Int? = null, val currentAppVersion: Int? = null, val passwordConfig: PasswordConfig = PasswordConfig.Initial, - val passwordHint: String? = null + val passwordHint: String? = null, + val lastPasswordLoginTime: Long? = null ) { fun isKeyPresent() = backupKey != null } diff --git a/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt b/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt index 9f949ede..a32bb57b 100644 --- a/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt +++ b/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt @@ -139,6 +139,12 @@ suspend fun Context.getPasswordHint(): String? { return getUserSettings().passwordHint } +suspend fun Context.updateLastPasswordLoginTime(lastPasswordLoginTime: Long?) { + getUserSettingsDataStore().updateData { + it.copy(lastPasswordLoginTime = lastPasswordLoginTime) + } +} + private val BACKUP_KEY = stringPreferencesKey("backup_key") private val BIOMETRIC_ENABLE = booleanPreferencesKey("biometric_enable") private val KEYPASS_PASSWORD = stringPreferencesKey("keypass_password")