Skip to content

Commit

Permalink
PM-13104: Log user out if biometrics is missing auth key and getting …
Browse files Browse the repository at this point in the history
…whether the user has a master password fails
  • Loading branch information
matt-livefront committed Oct 3, 2024
1 parent 4698b86 commit 7a4bc01
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ class VaultUnlockProcessor: StateProcessor<

let hasMasterPassword = try? await services.authRepository.hasMasterPassword()
let isPinEnabled = try? await services.authRepository.isPinUnlockAvailable()
if hasMasterPassword == false, isPinEnabled == false {
if hasMasterPassword == nil || hasMasterPassword == false, isPinEnabled == false {
// If biometrics is enabled, but the auth key doesn't exist and the user doesn't
// have a master password or PIN, log the user out.
await logoutUser(userInitiated: false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,40 @@ class VaultUnlockProcessorTests: BitwardenTestCase { // swiftlint:disable:this t
XCTAssertNil(coordinator.routes.last)
}

/// `perform(_:)` with `.unlockWithBiometrics` disables biometrics if the user's auth key doesn't
/// exist and they have a master password but no PIN.
@MainActor
func test_perform_unlockWithBiometrics_authRepoError_getAuthKeyFailed_masterPasswordWithoutPin() async throws {
biometricsRepository.biometricUnlockStatus = .success(
.available(.touchID, enabled: true)
)
authRepository.unlockVaultWithBiometricsResult = .failure(BiometricsServiceError.getAuthKeyFailed)
authRepository.allowBiometricUnlockResult = .success(())
authRepository.hasMasterPasswordResult = .success(true)
authRepository.isPinUnlockAvailableResult = .success(false)

await subject.perform(.unlockVaultWithBiometrics)
XCTAssertEqual(authRepository.allowBiometricUnlock, false)
XCTAssertNil(coordinator.routes.last)
}

/// `perform(_:)` with `.unlockWithBiometrics` disables biometrics if the user's auth key doesn't
/// exist and they have a PIN but no master password.
@MainActor
func test_perform_unlockWithBiometrics_authRepoError_getAuthKeyFailed_pinWithoutMasterPassword() async throws {
biometricsRepository.biometricUnlockStatus = .success(
.available(.touchID, enabled: true)
)
authRepository.unlockVaultWithBiometricsResult = .failure(BiometricsServiceError.getAuthKeyFailed)
authRepository.allowBiometricUnlockResult = .success(())
authRepository.hasMasterPasswordResult = .success(false)
authRepository.isPinUnlockAvailableResult = .success(true)

await subject.perform(.unlockVaultWithBiometrics)
XCTAssertEqual(authRepository.allowBiometricUnlock, false)
XCTAssertNil(coordinator.routes.last)
}

/// `perform(_:)` with `.unlockWithBiometrics` logs the user out if the user's auth key doesn't
/// exist and they don't have a master password or PIN.
@MainActor
Expand All @@ -643,6 +677,23 @@ class VaultUnlockProcessorTests: BitwardenTestCase { // swiftlint:disable:this t
XCTAssertEqual(coordinator.events, [.action(.logout(userId: nil, userInitiated: false))])
}

/// `perform(_:)` with `.unlockWithBiometrics` logs the user out if the user's auth key doesn't
/// exist and fetching whether they have a master password fails.
@MainActor
func test_perform_unlockWithBiometrics_authRepoError_getAuthKeyFailed_hasMasterPasswordError() async throws {
biometricsRepository.biometricUnlockStatus = .success(
.available(.touchID, enabled: true)
)
authRepository.unlockVaultWithBiometricsResult = .failure(BiometricsServiceError.getAuthKeyFailed)
authRepository.allowBiometricUnlockResult = .success(())
authRepository.hasMasterPasswordResult = .failure(BitwardenTestError.example)
authRepository.isPinUnlockAvailableResult = .success(false)

await subject.perform(.unlockVaultWithBiometrics)
XCTAssertEqual(authRepository.allowBiometricUnlock, false)
XCTAssertEqual(coordinator.events, [.action(.logout(userId: nil, userInitiated: false))])
}

/// `perform(_:)` with `.unlockWithBiometrics` handles user cancellation.
@MainActor
func test_perform_unlockWithBiometrics_userCancelled() async throws {
Expand Down

0 comments on commit 7a4bc01

Please sign in to comment.