Para Swift SDK provides robust session management, automatically tracking authentication states and ensuring secure, seamless interactions. Effective session management is critical for security, usability, and reliability of your application.

Session States

Para manages sessions using the ParaSessionState enum:

  • unknown: Initial state before the status is determined.
  • inactive: SDK initialized but no active session.
  • active: Session is active but user not fully logged in.
  • activeLoggedIn: User is fully logged in with an active session.

Observing Session States

Utilize SwiftUI’s Combine or other state management tools to observe changes:

@StateObject private var paraManager: ParaManager

.onChange(of: paraManager.sessionState) { newState in
  switch newState {
    case .activeLoggedIn:
      print("User authenticated")
    case .inactive:
      print("Session inactive")
    default:
      print("Session state: \(newState)")
  }
}

Session Duration

The Para session length is 2 hours by default, but can be configured to up to 30 days. To configure this parameter, please visit the Configuration section of the Developer Portal. A user signing a message or transaction extends the session by the duration of the session length.

Key Session Methods

  • isSessionActive() async throws -> Bool: Checks if the session is currently valid before performing authenticated operations.
  • isFullyLoggedIn() async throws -> Bool: Checks if the user is fully logged in with an active session.
  • exportSession() async throws -> String: Exports session state as a string that can be used for advanced integration scenarios.
  • logout() async throws: Clears the current session, removes all website data from the WebView, and resets the session state to inactive.

Maintaining Active Sessions

For long-running applications, check session status before performing sensitive operations:

func performSensitiveOperation() {
  Task {
    do {
      if try await paraManager.isSessionActive() {
        // Proceed with sensitive operation
        try await signTransaction(...)
      } else {
        // Handle session expiration - redirect to login
        navigateToLogin()
      }
    } catch {
      await MainActor.run {
        isLoggedIn = false
      }
    }
  }
}

Refreshing Expired Sessions

When a session has expired, Para recommends initiating a full authentication flow rather than trying to refresh the session.

For Swift applications, always call logout() before reinitiating authentication when a session has expired to ensure all stored data is properly cleared.

import ParaSwift

func handleSessionExpiration() async {
  do {
    // When session expires, first clear storage
    try await paraManager.logout()
    
    // Then redirect to authentication screen
    await MainActor.run {
      // Navigate to authentication screen
    }
  } catch {
    // Handle error
  }
}

Background Security

Clear sensitive data when app goes to background by logging out:

class AppDelegate: NSObject, UIApplicationDelegate {
  func applicationDidEnterBackground(_ application: UIApplication) {
    Task {
      try? await paraManager.logout()
    }
  }
}

Exporting Sessions to Your Server

In some advanced scenarios, you may need to export the session state:

func sendSessionToServer() async throws {
  do {
    // Export session without signing capabilities
    let sessionString = try await paraManager.exportSession()
    
    // Create URL request
    var request = URLRequest(url: URL(string: "https://your-api.com/sessions")!)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    
    // Create request body
    let body: [String: Any] = ["session": sessionString]
    request.httpBody = try JSONSerialization.data(withJSONObject: body)
    
    // Send request
    let (_, response) = try await URLSession.shared.data(for: request)
    
    guard let httpResponse = response as? HTTPURLResponse, 
          httpResponse.statusCode == 200 else {
      throw URLError(.badServerResponse)
    }
    
    // Handle success
  } catch {
    // Handle error
    throw error
  }
}

Best Practices

Check Sessions on App Launch

Verify session status when your app starts to determine if users need to reauthenticate:

import SwiftUI
import ParaSwift

class AppStartupManager: ObservableObject {
  @Published var isLoggedIn = false
  let paraManager: ParaManager
  
  init(paraManager: ParaManager) {
    self.paraManager = paraManager
    checkSessionOnLaunch()
  }
  
  func checkSessionOnLaunch() {
    Task {
      do {
        let isActive = try await paraManager.isSessionActive()
        await MainActor.run {
          if isActive {
            // User is logged in
            isLoggedIn = true
          } else {
            // Session not active, clear any lingering data
            Task {
              try? await paraManager.logout()
            }
            isLoggedIn = false
          }
        }
      } catch {
        await MainActor.run {
          isLoggedIn = false
        }
      }
    }
  }
}

Handle App Lifecycle Changes

Swift apps can be backgrounded and foregrounded, which may affect session status:

import SwiftUI
import ParaSwift

class LifecycleManager: ObservableObject {
  let paraManager: ParaManager
  
  init(paraManager: ParaManager) {
    self.paraManager = paraManager
    
    // Register for foreground notifications
    NotificationCenter.default.addObserver(
      self,
      selector: #selector(appMovedToForeground),
      name: UIApplication.willEnterForegroundNotification,
      object: nil
    )
  }
  
  @objc func appMovedToForeground() {
    // App came to foreground, check session
    checkSession()
  }
  
  func checkSession() {
    Task {
      let isActive = try? await paraManager.isSessionActive()
      if isActive != true {
        try? await paraManager.logout()
        await MainActor.run {
          // Navigate to login screen
        }
      }
    }
  }
  
  deinit {
    NotificationCenter.default.removeObserver(self)
  }
}

Next Steps

Explore more advanced features and integrations with Para in Swift: