> ## Documentation Index
> Fetch the complete documentation index at: https://docs.portalhq.io/llms.txt
> Use this file to discover all available pages before exploring further.

# restoreSession

> Rebuilds the persisted PortalSession from the Keychain on launch, or returns nil when the user is signed out.

**Function Signature**

```swift theme={null}
public func restoreSession() async throws -> PortalSession?
```

A `PortalAuth` method. Makes no network call. Reads the session persisted by the last successful `handleRedirect`, `signInWith*` or `verifyTotp` for this `authEnvironmentId` and wraps it in a `PortalSession` you can pass to `Portal(credentials:)`.

**Returns**

* **`PortalSession?`**:
  * A session when storage holds one. It is a credential worth trying, not proof of validity: a dead session is discovered by the first authenticated `Portal` call, which invalidates it and fires `onSessionInvalidated`.
  * **`nil`** when nothing usable is stored. This includes an entry that could not be parsed: the SDK clears it and reports "signed out", because no caller action could make it readable. Treat `nil` as "show the sign-in screen".

**Throws**

* `PortalAuthError.sessionStorageFailure(message:)`: The Keychain could not be read this time (a transient fault), or an unusable entry could not be cleared. Distinct from "no session", which is `nil`.

**Notes**

* Subscribe to `onSessionInvalidated` when you construct `Portal` from the restored session. `Portal.init` makes an authenticated request straight away; if the backend rejects a restored session there, your listener runs once even though it was added afterwards.
* **Keychain items survive app deletion.** A delete-and-reinstall can restore a still-live session from the previous install or, on a shared device, a previous user. For a clean slate, call `clearPersistedSession()` on the first launch after install, for example behind a `UserDefaults` flag.
* Sessions are keyed by `authEnvironmentId`, so any `PortalAuth` built with the same ID restores the same session.
* Session lifetime is decided by the backend: every authenticated request extends the token to 24 hours later, until seven days after it was issued. See [API Keys](/resources/api-keys#client-session-tokens).
* Available starting from SDK version 8.0.0.

**Example Usage**

```swift theme={null}
import Foundation
import PortalSwift

func restoreSessionOnLaunch() async {
    let defaults = UserDefaults.standard
    if !defaults.bool(forKey: "hasLaunchedBefore") {
        do {
            try await auth.clearPersistedSession()
            defaults.set(true, forKey: "hasLaunchedBefore")
        } catch {
            print("Error clearing the previous install's session: \(error)")
        }
    }

    do {
        guard let session = try await auth.restoreSession() else {
            showSignIn()
            return
        }

        let portal = try Portal(credentials: session)
        portal.onSessionInvalidated { [weak self] in
            self?.showSignIn()
        }
        self.portal = portal
        print("Restored the session for end user \(session.endUserId)")
    } catch {
        print("Error restoring the session: \(error)")
        showSignIn()
    }
}
```

**Related Documentation**

* [clearPersistedSession reference](./portalauthclearpersistedsession)
* [onSessionInvalidated reference](./onsessioninvalidated)
* [Restore the session on launch](../guide/client-auth#restore-the-session-on-launch)
