From 2eb9e7db2da7a034de44e9ff0f1375d1537ad30f Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Thu, 7 Dec 2023 23:45:53 +0530 Subject: [PATCH] macOS: Don't sign out on rebooting the Mac (#2816) Fixes #2809. Tested the case where the user: - while being signed in and connected in the Firezone app, logs out of macOS - logs in as another user In the above case, the app: - sees that there's a token reference stored in the tunnel, but is unable to access the token (the token is per user) - so the app signs the user out This PR is stacked on top of PR #2804. --- .../Helpers/TunnelShutdownEvent.swift | 5 ++- .../FirezoneKit/Stores/AuthStore.swift | 43 +++++++++++++------ .../FirezoneKit/Stores/TunnelStore.swift | 7 ++- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Helpers/TunnelShutdownEvent.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Helpers/TunnelShutdownEvent.swift index c8c1024bc..de4d2b3b8 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Helpers/TunnelShutdownEvent.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Helpers/TunnelShutdownEvent.swift @@ -39,6 +39,7 @@ public struct TunnelShutdownEvent: Codable, CustomStringConvertible { } public enum Action { + case doNothing case signoutImmediately case retryThenSignout } @@ -50,8 +51,10 @@ public struct TunnelShutdownEvent: Codable, CustomStringConvertible { public var action: Action { switch reason { case .stopped(let reason): - if reason == .userInitiated || reason == .userLogout || reason == .userSwitch { + if reason == .userInitiated { return .signoutImmediately + } else if reason == .userLogout || reason == .userSwitch { + return .doNothing } else { return .retryThenSignout } diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/AuthStore.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/AuthStore.swift index c4fe8ef61..88fa384c5 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/AuthStore.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/AuthStore.swift @@ -88,6 +88,9 @@ final class AuthStore: ObservableObject { .sink { [weak self] status in guard let self = self else { return } Task { + if status == .disconnected { + self.handleTunnelDisconnectionEvent() + } if status == .connected { self.resetReconnectionAttemptsRemaining() } @@ -170,26 +173,40 @@ final class AuthStore: ObservableObject { do { try await tunnelStore.start() } catch { - logger.error("\(#function): Error starting tunnel: \(String(describing: error))") - if let tsEvent = TunnelShutdownEvent.loadFromDisk() { - self.logger.log( - "\(#function): Tunnel shutdown event: \(tsEvent, privacy: .public)" + if case TunnelStoreError.startTunnelErrored(let startTunnelError) = error { + logger.error( + "\(#function): Starting tunnel errored: \(String(describing: startTunnelError))" ) - switch tsEvent.action { - case .signoutImmediately: - Task { - await self.signOut() - } - case .retryThenSignout: - self.retryStartTunnel() - } + handleTunnelDisconnectionEvent() } else { - self.logger.log("\(#function): Tunnel shutdown event not found") + logger.error("\(#function): Starting tunnel failed: \(String(describing: error))") + // Disconnection event will be handled in the tunnel status change handler } } } } + func handleTunnelDisconnectionEvent() { + logger.log("\(#function)") + if let tsEvent = TunnelShutdownEvent.loadFromDisk() { + self.logger.log( + "\(#function): Tunnel shutdown event: \(tsEvent, privacy: .public)" + ) + switch tsEvent.action { + case .signoutImmediately: + Task { + await self.signOut() + } + case .retryThenSignout: + self.retryStartTunnel() + case .doNothing: + break + } + } else { + self.logger.log("\(#function): Tunnel shutdown event not found") + } + } + func retryStartTunnel() { // Try to reconnect, but don't try more than 3 times at a time. // If this gets called the third time, sign out. diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/TunnelStore.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/TunnelStore.swift index 6323009b0..99b3386b3 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/TunnelStore.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/TunnelStore.swift @@ -15,6 +15,7 @@ enum TunnelStoreError: Error { case cannotSaveToTunnelWhenConnected case cannotSignOutWhenConnected case stopAlreadyBeingAttempted + case startTunnelErrored(Error) } public struct TunnelProviderKeys { @@ -173,7 +174,11 @@ final class TunnelStore: ObservableObject { try await tunnel.loadFromPreferences() let session = castToSession(tunnel.connection) - try session.startTunnel() + do { + try session.startTunnel() + } catch { + throw TunnelStoreError.startTunnelErrored(error) + } try await withCheckedThrowingContinuation { continuation in self.startTunnelContinuation = continuation }