Logout automatically when pin/biometrics provided wrong too many times

This commit is contained in:
ismailgulek
2020-09-29 16:57:46 +03:00
parent 3750afcab7
commit 10664938c8
7 changed files with 77 additions and 13 deletions
@@ -41,6 +41,7 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
weak var viewDelegate: EnterPinCodeViewModelViewDelegate?
weak var coordinatorDelegate: EnterPinCodeViewModelCoordinatorDelegate?
private let pinCodePreferences: PinCodePreferences
private let localAuthenticationService: LocalAuthenticationService
// MARK: - Setup
@@ -49,6 +50,7 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
self.originalViewMode = viewMode
self.viewMode = viewMode
self.pinCodePreferences = pinCodePreferences
self.localAuthenticationService = LocalAuthenticationService(pinCodePreferences: pinCodePreferences)
}
// MARK: - Public
@@ -141,6 +143,12 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
if currentPin != pinCodePreferences.pin {
// no match
numberOfFailuresDuringEnterPIN += 1
pinCodePreferences.numberOfPinFailures += 1
if viewMode == .unlock && localAuthenticationService.shouldLogOutUser() {
// log out user
self.coordinatorDelegate?.enterPinCodeViewModelDidCompleteWithReset(self)
return
}
if numberOfFailuresDuringEnterPIN < pinCodePreferences.allowedNumberOfTrialsBeforeAlert {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.viewDelegate?.enterPinCodeViewModel(self, didUpdateViewState: .wrongPin)
@@ -153,6 +161,9 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
}
} else {
// match
// we can use biometrics anymore, if set
pinCodePreferences.canUseBiometricsToUnlock = nil
pinCodePreferences.resetCounters()
// complete with a little delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.coordinatorDelegate?.enterPinCodeViewModelDidComplete(self)
@@ -176,7 +176,7 @@ final class PinCodePreferences: NSObject {
}
var isBiometricsSet: Bool {
return biometricsEnabled == true
return biometricsEnabled == true && canUseBiometricsToUnlock == true
}
func localizedBiometricsName() -> String? {
@@ -53,8 +53,7 @@ final class SetPinCoordinator: SetPinCoordinatorType {
private func getRootCoordinator() -> Coordinator & Presentable {
switch viewMode {
case .unlock:
let canUseBiometricsToUnlock = pinCodePreferences.canUseBiometricsToUnlock ?? true
if pinCodePreferences.isBiometricsSet && canUseBiometricsToUnlock {
if pinCodePreferences.isBiometricsSet {
return createSetupBiometricsCoordinator()
} else {
return createEnterPinCodeCoordinator()
@@ -139,6 +138,7 @@ extension SetPinCoordinator: EnterPinCodeCoordinatorDelegate {
func enterPinCodeCoordinatorDidCompleteWithReset(_ coordinator: EnterPinCodeCoordinatorType) {
self.delegate?.setPinCoordinatorDidCompleteWithReset(self)
pinCodePreferences.reset()
}
func enterPinCodeCoordinator(_ coordinator: EnterPinCodeCoordinatorType, didCompleteWithPin pin: String) {
@@ -171,7 +171,13 @@ extension SetPinCoordinator: SetupBiometricsCoordinatorDelegate {
}
func setupBiometricsCoordinatorDidCompleteWithReset(_ coordinator: SetupBiometricsCoordinatorType) {
self.delegate?.setPinCoordinatorDidCompleteWithReset(self)
if viewMode == .unlock && pinCodePreferences.isPinSet {
// and user also has set a pin, so fallback to it
setRootCoordinator(createEnterPinCodeCoordinator())
} else {
// cascade rest
self.delegate?.setPinCoordinatorDidCompleteWithReset(self)
}
}
func setupBiometricsCoordinatorDidCancel(_ coordinator: SetupBiometricsCoordinatorType) {
@@ -28,6 +28,7 @@ final class SetupBiometricsViewModel: SetupBiometricsViewModelType {
private let session: MXSession?
private let viewMode: SetPinCoordinatorViewMode
private let pinCodePreferences: PinCodePreferences
private let localAuthenticationService: LocalAuthenticationService
// MARK: Public
@@ -40,6 +41,7 @@ final class SetupBiometricsViewModel: SetupBiometricsViewModelType {
self.session = session
self.viewMode = viewMode
self.pinCodePreferences = pinCodePreferences
self.localAuthenticationService = LocalAuthenticationService(pinCodePreferences: pinCodePreferences)
}
deinit {
@@ -74,26 +76,47 @@ final class SetupBiometricsViewModel: SetupBiometricsViewModelType {
// MARK: - Private
private func enableDisableBiometrics() {
LocalAuthenticationService.isShowingBiometrics = true
LAContext().evaluatePolicy(.deviceOwnerAuthentication, localizedReason: VectorL10n.biometricsUsageReason) { (success, error) in
if success {
// complete after a little delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.pinCodePreferences.canUseBiometricsToUnlock = nil
self.pinCodePreferences.resetCounters()
self.coordinatorDelegate?.setupBiometricsViewModelDidComplete(self)
LocalAuthenticationService.isShowingBiometrics = false
}
} else {
LocalAuthenticationService.isShowingBiometrics = false
}
}
}
private func unlockWithBiometrics() {
LocalAuthenticationService.isShowingBiometrics = true
LAContext().evaluatePolicy(.deviceOwnerAuthentication, localizedReason: VectorL10n.biometricsUsageReason) { (success, error) in
if success {
// complete after a little delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.pinCodePreferences.canUseBiometricsToUnlock = nil
self.pinCodePreferences.resetCounters()
self.coordinatorDelegate?.setupBiometricsViewModelDidComplete(self)
LocalAuthenticationService.isShowingBiometrics = false
}
} else {
if let error = error as NSError?, error.code == LAError.Code.userCancel.rawValue || error.code == LAError.Code.userFallback.rawValue {
self.userCancelledUnlockWithBiometrics()
if let error = error as NSError? {
self.pinCodePreferences.numberOfBiometricsFailures += 1
if self.localAuthenticationService.shouldLogOutUser() {
// biometrics can't be used until further unlock with pin or a new log in
self.pinCodePreferences.canUseBiometricsToUnlock = false
DispatchQueue.main.async {
self.coordinatorDelegate?.setupBiometricsViewModelDidCompleteWithReset(self)
LocalAuthenticationService.isShowingBiometrics = false
}
} else if error.code == LAError.Code.userCancel.rawValue || error.code == LAError.Code.userFallback.rawValue {
self.userCancelledUnlockWithBiometrics()
LocalAuthenticationService.isShowingBiometrics = false
}
}
}
}
@@ -101,6 +124,7 @@ final class SetupBiometricsViewModel: SetupBiometricsViewModelType {
private func userCancelledUnlockWithBiometrics() {
if pinCodePreferences.isPinSet {
self.pinCodePreferences.canUseBiometricsToUnlock = false
// cascade this cancellation, coordinator should take care of it
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.coordinatorDelegate?.setupBiometricsViewModelDidCancel(self)