diff --git a/BitwardenShared/Core/Platform/Services/StateService.swift b/BitwardenShared/Core/Platform/Services/StateService.swift index c2d8ce286..94f99aadc 100644 --- a/BitwardenShared/Core/Platform/Services/StateService.swift +++ b/BitwardenShared/Core/Platform/Services/StateService.swift @@ -1494,11 +1494,19 @@ actor DefaultStateService: StateService { // swiftlint:disable:this type_body_le func getVaultTimeout(userId: String?) async throws -> SessionTimeoutValue { let userId = try getAccount(userId: userId).profile.userId + let userAuthKey = try? await keychainRepository.getUserAuthKeyValue(for: .neverLock(userId: userId)) guard let rawValue = appSettingsStore.vaultTimeout(userId: userId) else { - let userAuthKey = try? await keychainRepository.getUserAuthKeyValue(for: .neverLock(userId: userId)) - return userAuthKey == nil ? .fifteenMinutes : .never + // If there isn't a stored value, it may be because MAUI stored `nil` for never timeout. + // So if the never lock key exists, set the timeout to never, otherwise to default. + return userAuthKey != nil ? .never : .fifteenMinutes } - return SessionTimeoutValue(rawValue: rawValue) + + let timeoutValue = SessionTimeoutValue(rawValue: rawValue) + if timeoutValue == .never, userAuthKey == nil { + // If never lock but no key (possibly due to logging out), return the default timeout. + return .fifteenMinutes + } + return timeoutValue } func isAuthenticated(userId: String?) async throws -> Bool { diff --git a/BitwardenShared/Core/Platform/Services/StateServiceTests.swift b/BitwardenShared/Core/Platform/Services/StateServiceTests.swift index ce84edce1..eaddba14d 100644 --- a/BitwardenShared/Core/Platform/Services/StateServiceTests.swift +++ b/BitwardenShared/Core/Platform/Services/StateServiceTests.swift @@ -999,6 +999,17 @@ class StateServiceTests: BitwardenTestCase { // swiftlint:disable:this type_body XCTAssertEqual(vaultTimeout, .never) } + /// `getVaultTimeout(userId:)` returns the default timeout if the user has a never lock value + /// stored but the never lock key doesn't exist. + func test_getVaultTimeout_neverLock_missingKey() async throws { + appSettingsStore.vaultTimeout["1"] = -2 + + await subject.addAccount(.fixture(profile: .fixture(userId: "1"))) + + let vaultTimeout = try await subject.getVaultTimeout() + XCTAssertEqual(vaultTimeout, .fifteenMinutes) + } + /// `lastSyncTimePublisher()` returns a publisher for the user's last sync time. func test_lastSyncTimePublisher() async throws { await subject.addAccount(.fixture(profile: .fixture(userId: "1")))