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

# Session Management — SocketFi Access Tokens & Storage

> Learn how SocketFi sessions work, how to store and use access tokens, manage session expiration, and build a React Context for authenticated state.

Every time a user successfully authenticates, SocketFi creates a session — a short-lived proof of identity that your application uses to identify the user and authorize requests to your backend. Sessions are separate from the wallet itself: a session can expire or be cleared without affecting the wallet, its balances, or any on-chain state. Understanding sessions is essential for building a secure, responsive application on top of SocketFi.

## What Is a Session?

A session represents a recently verified user. It contains two pieces of information:

```typescript theme={null}
interface Session {
  userProfile: {
    id: string;         // Stable, permanent user identifier
    username?: string;  // User's display name, if set
  };
  socketfiAccessToken: string; // Signed JWT — your proof of authentication
}
```

The `socketfiAccessToken` is a signed JSON Web Token (JWT). It encodes the user's identity and wallet association, and it is cryptographically signed by SocketFi so your backend can verify it without making an additional network call to SocketFi's servers.

***

## Using the Access Token

Attach the access token to every request your application makes to your own backend. Use the standard `Authorization: Bearer` header:

```typescript theme={null}
const session = await socketfi.authenticate();

const response = await fetch("/api/wallet/balance", {
  headers: {
    Authorization: `Bearer ${session.socketfiAccessToken}`,
  },
});
```

Your backend receives this header, verifies the token with `@socketfi/server`, and extracts the user identity and wallet address. See [Backend Verification](/authentication/backend-verification) for the complete server-side flow.

<Warning>
  Never use the `socketfiAccessToken` as a primary key or store it as a user identifier. Use `session.userProfile.id` as your stable foreign key. The access token changes every time the user re-authenticates.
</Warning>

***

## Session Storage

Where you store the session depends on your platform.

<Tabs>
  <Tab title="React (Web)">
    For web applications, `localStorage` works well for persisting the token across page reloads. Pair it with React state for in-memory access during the session.

    ```typescript theme={null}
    // After authentication
    const session = await socketfi.authenticate();
    localStorage.setItem("socketfi_token", session.socketfiAccessToken);

    // On app startup — restore from storage
    const storedToken = localStorage.getItem("socketfi_token");

    // On logout — clear everything
    localStorage.removeItem("socketfi_token");
    ```

    <Note>
      `localStorage` is accessible to JavaScript on the same origin. If your application has a Content Security Policy and is not susceptible to XSS, this is an acceptable trade-off for usability. For higher-security applications, consider storing the token in an `httpOnly` cookie set by your own backend.
    </Note>
  </Tab>

  <Tab title="React Native">
    Use `AsyncStorage` for simple persistence or `expo-secure-store` for hardware-backed encrypted storage (recommended for production).

    ```typescript theme={null}
    import AsyncStorage from "@react-native-async-storage/async-storage";

    // Store after authentication
    await AsyncStorage.setItem("socketfi_token", session.socketfiAccessToken);

    // Restore on app launch
    const token = await AsyncStorage.getItem("socketfi_token");

    // Clear on logout
    await AsyncStorage.removeItem("socketfi_token");
    ```

    ```typescript theme={null}
    import * as SecureStore from "expo-secure-store";

    // Encrypted storage (recommended for production)
    await SecureStore.setItemAsync("socketfi_token", session.socketfiAccessToken);
    const token = await SecureStore.getItemAsync("socketfi_token");
    await SecureStore.deleteItemAsync("socketfi_token");
    ```
  </Tab>
</Tabs>

***

## React Context Example

For most React applications, a Context provider is the cleanest way to share session state across your component tree.

```typescript theme={null}
import React, { createContext, useContext, useState, useEffect } from "react";
import { socketfi } from "./socketfi"; // Your initialized SocketFi instance

interface SessionContextValue {
  user: { id: string; username?: string } | null;
  token: string | null;
  signIn: () => Promise<void>;
  signOut: () => void;
}

const SessionContext = createContext<SessionContextValue | null>(null);

export function SessionProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<{ id: string; username?: string } | null>(null);
  const [token, setToken] = useState<string | null>(null);

  // Restore session from storage on mount
  useEffect(() => {
    const storedToken = localStorage.getItem("socketfi_token");
    const storedUser = localStorage.getItem("socketfi_user");
    if (storedToken && storedUser) {
      setToken(storedToken);
      setUser(JSON.parse(storedUser));
    }
  }, []);

  async function signIn() {
    const session = await socketfi.authenticate();
    setUser(session.userProfile);
    setToken(session.socketfiAccessToken);
    localStorage.setItem("socketfi_token", session.socketfiAccessToken);
    localStorage.setItem("socketfi_user", JSON.stringify(session.userProfile));
  }

  function signOut() {
    setUser(null);
    setToken(null);
    localStorage.removeItem("socketfi_token");
    localStorage.removeItem("socketfi_user");
  }

  return (
    <SessionContext.Provider value={{ user, token, signIn, signOut }}>
      {children}
    </SessionContext.Provider>
  );
}

export function useSession() {
  const ctx = useContext(SessionContext);
  if (!ctx) throw new Error("useSession must be used within SessionProvider");
  return ctx;
}
```

Use it in your components:

```typescript theme={null}
function Dashboard() {
  const { user, token, signOut } = useSession();

  return (
    <div>
      <p>Welcome, {user?.username}</p>
      <button onClick={signOut}>Sign Out</button>
    </div>
  );
}
```

***

## Session Expiration

Sessions are intentionally short-lived. When a `socketfiAccessToken` expires, your backend will return an HTTP `401` response to requests that include it. Design your application to handle this without disrupting the user experience:

```typescript theme={null}
async function authorizedFetch(url: string, options: RequestInit = {}) {
  const { token, signIn } = useSessionStore(); // however you access your token

  const response = await fetch(url, {
    ...options,
    headers: {
      ...options.headers,
      Authorization: `Bearer ${token}`,
    },
  });

  if (response.status === 401) {
    // Prompt re-authentication and retry
    await signIn();
    const freshToken = getToken();
    return fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        Authorization: `Bearer ${freshToken}`,
      },
    });
  }

  return response;
}
```

<Tip>
  Proactively decode the JWT on the client and check the `exp` claim before making requests. This lets you trigger re-authentication before an API call fails, resulting in a smoother user experience.
</Tip>

***

## Sessions vs. Wallets

It is important to understand that sessions and wallets are completely independent.

| Session               | Wallet                       |
| --------------------- | ---------------------------- |
| Temporary — expires   | Permanent — persists forever |
| Cleared on logout     | Unchanged by logout          |
| New token on re-auth  | Same address on re-auth      |
| Proof of recent login | Proof of on-chain ownership  |

```text theme={null}
Session Expires
  ↓
Wallet Still Exists (all assets intact)
  ↓
User Re-authenticates
  ↓
Same Wallet, New Session Token
```

Signing out does not delete, freeze, or affect the wallet in any way.

***

## Common Session Errors

| Error               | Cause                                     | Resolution                                                                  |
| ------------------- | ----------------------------------------- | --------------------------------------------------------------------------- |
| `Missing Token`     | No `Authorization` header was sent        | Ensure your fetch wrapper always attaches the stored token                  |
| `Invalid Token`     | The JWT is malformed or was tampered with | Never modify the raw token string; re-authenticate to get a fresh one       |
| `Expired Token`     | The JWT `exp` claim has passed            | Call `socketfi.authenticate()` to get a new session                         |
| `Invalid Signature` | The token was not signed by SocketFi      | Treat this as a security event — do not grant access; alert your monitoring |

***

## Security Best Practices

* **Always verify tokens server-side.** Frontend session state tells you who the user claims to be. The `verifyAuth()` call tells you who they actually are.
* **Use HTTPS exclusively.** Session tokens transmitted over plain HTTP can be intercepted. All production traffic must be encrypted.
* **Store minimal data.** Persist only the token and the user profile. Do not store wallet addresses, balance data, or other wallet state in session storage.
* **Handle expiration gracefully.** Build automatic re-authentication into your data-fetching layer so users are not unexpectedly locked out.
