# Session Management (SessionProvider)

The `SessionProvider` is the cornerstone of the `@arcblock/did-connect-react` library. It's a React Context Provider that encapsulates all session-related logic, state, and actions. By wrapping your application with `SessionProvider`, you make the user's session information and authentication methods available to any component in your application tree, without having to pass props down manually.

This component handles everything from storing session tokens and managing user data to orchestrating login/logout flows and refreshing sessions automatically.

## How It Works

`SessionProvider` creates a session context that holds the current user's state (`user` object, `loading` status, etc.) and provides functions to modify that state (e.g., `login`, `logout`). Any component nested within `SessionProvider` can subscribe to this context to access this data and trigger authentication actions.

Here is a diagram illustrating the basic architecture:

<!-- DIAGRAM_IMAGE_START:architecture:4:3:1765962229 -->
![Session Management (SessionProvider)](assets/diagram/core-components-session-provider-01.jpg)
<!-- DIAGRAM_IMAGE_END -->

## Getting Started

To use the session management features, you first need to import and wrap your application with `SessionProvider`. The library exports factory functions to create a configured provider.

### Basic Setup

The most common way to set up the provider is by using `createAuthServiceSessionContext`, which is pre-configured for applications running within the ArcBlock ecosystem (Blocklets).

```javascript App.js icon=logos:javascript
import React from 'react';
import { createAuthServiceSessionContext } from '@arcblock/did-connect-react/lib/Session';
import AuthButton from './AuthButton';

// Create the SessionProvider and a hook to access the context
const { SessionProvider, SessionContext } = createAuthServiceSessionContext();

export const useSession = () => React.useContext(SessionContext);

export default function App() {
  return (
    <SessionProvider>
      <div className="App">
        <h1>Welcome to DID Connect</h1>
        <AuthButton />
      </div>
    </SessionProvider>
  );
}
```

```javascript AuthButton.js icon=logos:javascript
import React from 'react';
import { useSession } from './App';

export default function AuthButton() {
  const { session } = useSession();

  if (session.loading) {
    return <div>Loading...</div>;
  }

  if (session.user) {
    return (
      <div>
        <p>Welcome, {session.user.fullName || session.user.did}</p>
        <button onClick={() => session.logout()}>Logout</button>
      </div>
    );
  }

  return <button onClick={() => session.login()}>Login</button>;
}
```

In this example, `createAuthServiceSessionContext` generates a `SessionProvider`. We wrap our `App` with it, and now any child component, like `AuthButton`, can use the `useSession` hook to access session data and functions.

## SessionProvider Props

You can configure the `SessionProvider`'s behavior by passing it various props.

<x-field-group>
  <x-field data-name="serviceHost" data-type="string" data-desc="The base URL for the authentication service backend. Defaults to the current Blocklet's prefix or '/'."></x-field>
  <x-field data-name="autoConnect" data-type="boolean" data-default="false" data-desc="If true, the DID Connect dialog will automatically open if no user session is found on page load."></x-field>
  <x-field data-name="autoDisconnect" data-type="boolean" data-default="true" data-desc="If true, the session will be automatically cleared if the application ID mismatches the one stored in the session cookie."></x-field>
  <x-field data-name="protectedRoutes" data-type="string[]" data-default='["*"]' data-desc="An array of route patterns to protect. If a non-authenticated user tries to access these routes, they will see a loading spinner until the session is resolved. Wildcards (*) are supported."></x-field>
  <x-field data-name="locale" data-type="string" data-desc="Sets the display language for the DID Connect UI. Defaults to the browser's language."></x-field>
  <x-field data-name="webWalletUrl" data-type="string" data-desc="The URL of the web-based DID Wallet to use for the connection process."></x-field>
  <x-field data-name="timeout" data-type="number" data-default="120000" data-desc="The timeout in milliseconds for waiting for a response from DID Wallet during the connection process."></x-field>
  <x-field data-name="useSocket" data-type="boolean" data-default="true" data-desc="Determines whether to use WebSockets for real-time communication with the wallet, providing a faster user experience."></x-field>
  <x-field data-name="extraParams" data-type="object" data-desc="An object of extra parameters to be sent with every authentication request to the backend."></x-field>
</x-field-group>

## The Session Context Object

When you consume the `SessionContext`, you get an object containing the session state and API. The primary property is `session`, which holds all the data and methods you'll interact with.

### State Properties

These are read-only properties that describe the current state of the user session.

<x-field-group>
  <x-field data-name="user" data-type="User | null" data-desc="The authenticated user object if a session exists, otherwise null. Contains details like DID, name, email, avatar, etc."></x-field>
  <x-field data-name="loading" data-type="boolean" data-desc="True when the session is being initialized, refreshed, or during a login/logout process."></x-field>
  <x-field data-name="initialized" data-type="boolean" data-desc="True once the initial session check has completed on page load."></x-field>
  <x-field data-name="open" data-type="boolean" data-desc="True if the DID Connect dialog is currently open."></x-field>
  <x-field data-name="error" data-type="string" data-desc="Contains an error message if the last session operation failed."></x-field>
  <x-field data-name="provider" data-type="string" data-desc="The provider used for the last login (e.g., 'wallet', 'github', 'google')."></x-field>
  <x-field data-name="walletOS" data-type="string" data-desc="The operating system of the connected DID Wallet (e.g., 'ios', 'android', 'web')."></x-field>
  <x-field data-name="unReadCount" data-type="number" data-desc="The number of unread notifications for the current user."></x-field>
</x-field-group>

### Action Methods

These are functions you can call to initiate authentication flows or manage the session.

<x-field-group>
  <x-field data-name="login()" data-type="function">
    <x-field-desc markdown>Initiates the user login process by opening the DID Connect UI. It accepts optional callbacks and parameters.</x-field-desc>
  </x-field>
  <x-field data-name="logout()" data-type="function">
    <x-field-desc markdown>Logs the current user out, clearing the session from storage. It accepts an optional callback function to be executed upon completion.</x-field-desc>
  </x-field>
  <x-field data-name="switchDid()" data-type="function">
    <x-field-desc markdown>Allows a logged-in user to switch to a different DID account. It re-opens the DID Connect UI with a context for switching accounts.</x-field-desc>
  </x-field>
  <x-field data-name="bindWallet()" data-type="function">
    <x-field-desc markdown>For users logged in via social providers (OAuth) or Passkeys, this function initiates a flow to connect a DID Wallet to their existing account.</x-field-desc>
  </x-field>
  <x-field data-name="refresh()" data-type="function">
    <x-field-desc markdown>Manually triggers a refresh of the user's session data from the server. Useful for fetching updated profile information or permissions.</x-field-desc>
  </x-field>
  <x-field data-name="switchProfile()" data-type="function">
    <x-field-desc markdown>Opens the DID Connect UI to allow the user to switch between different profiles within the same DID account (e.g., personal, work).</x-field-desc>
  </x-field>
  <x-field data-name="switchPassport()" data-type="function">
    <x-field-desc markdown>Opens the DID Connect UI to allow the user to switch between different passports, which may represent different sets of credentials or roles.</x-field-desc>
  </x-field>
  <x-field data-name="connectToDidSpaceForFullAccess()" data-type="function">
    <x-field-desc markdown>Initiates a connection to the user's DID Space, requesting full access permissions. This is often required for applications that need to read and write data to the user's personal data store.</x-field-desc>
  </x-field>
  <x-field data-name="withSecondaryAuth()" data-type="function">
    <x-field-desc markdown>A higher-order function that wraps another function, requiring the user to complete a secondary authentication step (e.g., re-enter password, use passkey) before the wrapped function is executed. This is ideal for protecting sensitive actions.</x-field-desc>
  </x-field>
</x-field-group>

### Event Subscription

The context also provides an `events` object, which is an instance of `EventEmitter3`. You can use it to subscribe to various lifecycle events of the session.

```javascript EventListener.js icon=logos:javascript
import React, { useEffect } from 'react';
import { useSession } from './App';

function EventListener() {
  const { events } = useSession();

  useEffect(() => {
    const handleLogin = (result) => {
      console.log('User logged in:', result.user.did);
    };

    const handleLogout = () => {
      console.log('User logged out');
    };

    events.on('login', handleLogin);
    events.on('logout', handleLogout);

    // Cleanup listeners on component unmount
    return () => {
      events.off('login', handleLogin);
      events.off('logout', handleLogout);
    };
  }, [events]);

  return null; // This component doesn't render anything
}
```

Available events include `login`, `login-failed`, `logout`, `change`, `bind-wallet`, `switch-passport`, and more.

## Advanced Customization

For scenarios that require different storage mechanisms or more granular control, you can use the generic `createSessionContext` factory.

```javascript customSession.js icon=logos:javascript
import { createSessionContext } from '@arcblock/did-connect-react/lib/Session';

const { SessionProvider, SessionContext } = createSessionContext(
  'my_app_session_token', // Custom storage key
  'ls',                   // Use localStorage instead of cookies
  {},
  {
    rolling: false,         // Disable automatic token refresh
  }
);

// ... export and use as needed
```

This allows you to fine-tune session behavior, such as changing the storage engine to `localStorage` ('ls') or `cookie`, or adjusting token refresh policies.
