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

# Token Management

> Complete guide to authentication and token management in the TypeScript SDK

The CommerceEngine SDK provides two sophisticated approaches to token management, designed to handle everything from simple prototyping to production-scale applications with automatic token refresh and persistence.

## Overview

<CardGroup cols={2}>
  <Card title="Manual Token Management" icon="file-pen">
    Simple approach where you handle token storage and refresh logic yourself
  </Card>

  <Card title="Automatic Token Management" icon="wand-magic-sparkles">
    Production-ready approach with automatic token refresh, persistence, and cleanup
  </Card>
</CardGroup>

## Manual Token Management

Perfect for prototyping, testing, or when you need full control over token handling.

### Basic Setup

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { createStorefront } from "@commercengine/storefront";

const sdk = createStorefront({
  storeId: "your-store-id",
  apiKey: "your-api-key",
  // No tokenStorage provided = manual mode
});
```

### Authentication Flow

<Steps>
  <Step title="Get anonymous token">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const { data, error } = await sdk.auth.getAnonymousToken();

    if (data) {
      // Manually set tokens
      await sdk.setTokens(data.access_token, data.refresh_token);
    }
    ```
  </Step>

  <Step title="Login with credentials">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const { data: loginData } = await sdk.auth.loginWithPassword({
      email: "user@example.com",
      password: "password"
    });

    if (loginData) {
      // Update tokens after login
      await sdk.setTokens(loginData.access_token, loginData.refresh_token);
    }
    ```
  </Step>

  <Step title="Handle token refresh manually">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // Check if user is logged in
    const isLoggedIn = await sdk.isLoggedIn();

    if (!isLoggedIn) {
      // Token might be expired, try to refresh
      const refreshToken = getStoredRefreshToken(); // Your storage logic
      
      const { data: refreshData } = await sdk.auth.refreshToken({
        refresh_token: refreshToken
      });
      
      if (refreshData) {
        await sdk.setTokens(refreshData.access_token, refreshData.refresh_token);
      }
    }
    ```
  </Step>
</Steps>

### Manual Mode Methods

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
// Set tokens for all clients
await sdk.setTokens(accessToken, refreshToken);

// Clear all tokens
await sdk.clearTokens();

// Check authentication status
const isLoggedIn = await sdk.isLoggedIn();
const isAnonymous = await sdk.isAnonymous();

// Get user information from the API
const { data: userData } = await sdk.auth.retrieveUser();
const user = userData?.user;
const userId = user?.id;
```

## Automatic Token Management

**Recommended for production applications.** Handles token refresh, storage, and cleanup automatically.

### Token Storage Options

#### Browser localStorage Storage

<Tabs>
  <Tab title="Basic Usage">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    import { createStorefront }, { BrowserTokenStorage } from "@commercengine/storefront";

    const sdk = createStorefront({
      storeId: "your-store-id",
      apiKey: "your-api-key",
      tokenStorage: new BrowserTokenStorage("myapp_") // Optional prefix
    });
    ```
  </Tab>

  <Tab title="With Callbacks">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const sdk = createStorefront({
      storeId: "your-store-id",
      apiKey: "your-api-key",
      tokenStorage: new BrowserTokenStorage("myapp_"),
      
      // Handle token lifecycle events
      onTokensUpdated: (accessToken, refreshToken) => {
        console.log("User authenticated successfully");
        // Optional: Update UI state, analytics, etc.
      },
      
      onTokensCleared: () => {
        console.log("User logged out");
        // Optional: Redirect to login, clear user state, etc.
      }
    });
    ```
  </Tab>
</Tabs>

**Features:**

* ✅ Persists across browser sessions
* ✅ Automatic token refresh
* ✅ Cross-tab synchronization
* ✅ Works with SPA frameworks (React, Vue, Angular)

#### Cookie Storage (SSR Compatible)

<Tabs>
  <Tab title="Basic Setup">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    import { CookieTokenStorage } from "@commercengine/storefront";

    const sdk = createStorefront({
      storeId: "your-store-id",
      apiKey: "your-api-key",
      tokenStorage: new CookieTokenStorage({
        prefix: "myapp_",
        maxAge: 7 * 24 * 60 * 60, // 7 days
        secure: true,
        sameSite: "Lax"
      })
    });
    ```
  </Tab>

  <Tab title="Next.js Example">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // Perfect for Next.js applications
    const sdk = createStorefront({
      storeId: process.env.NEXT_PUBLIC_STORE_ID!,
      apiKey: process.env.NEXT_PUBLIC_API_KEY!,
      tokenStorage: new CookieTokenStorage({
        prefix: "myapp_",
        secure: process.env.NODE_ENV === "production",
        domain: process.env.NODE_ENV === "production" ? ".mysite.com" : undefined
      })
    });
    ```
  </Tab>
</Tabs>

**Features:**

* ✅ SSR/SSG compatible
* ✅ Server and client access
* ✅ Cross-subdomain sharing
* ✅ Automatic expiry handling

#### Memory Storage (Server-Side)

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { MemoryTokenStorage } from "@commercengine/storefront";

const sdk = createStorefront({
  storeId: "your-store-id",
  apiKey: "your-api-key",
  tokenStorage: new MemoryTokenStorage()
});

// Perfect for:
// - Server-side API routes
// - Background jobs
// - Testing environments
```

**Features:**

* ✅ Fast in-memory access
* ✅ No persistence overhead
* ✅ Perfect for server environments
* ✅ Automatic cleanup on process end

### Custom Token Storage

Implement the `TokenStorage` interface for custom storage solutions:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { TokenStorage } from "@commercengine/storefront";

class RedisTokenStorage implements TokenStorage {
  constructor(private redisClient: RedisClient, private userId: string) {}

  async getAccessToken(): Promise<string | null> {
    return await this.redisClient.get(`user:${this.userId}:access_token`);
  }

  async setAccessToken(token: string): Promise<void> {
    await this.redisClient.setex(`user:${this.userId}:access_token`, 3600, token);
  }

  async getRefreshToken(): Promise<string | null> {
    return await this.redisClient.get(`user:${this.userId}:refresh_token`);
  }

  async setRefreshToken(token: string): Promise<void> {
    await this.redisClient.setex(`user:${this.userId}:refresh_token`, 86400 * 7, token);
  }

  async clearTokens(): Promise<void> {
    await this.redisClient.del([
      `user:${this.userId}:access_token`,
      `user:${this.userId}:refresh_token`
    ]);
  }
}

// Use custom storage
const sdk = createStorefront({
  storeId: "your-store-id",
  apiKey: "your-api-key",
  tokenStorage: new RedisTokenStorage(redisClient, userId)
});
```

## Authentication Patterns

### Anonymous to Authenticated Flow

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { createStorefront }, { BrowserTokenStorage } from "@commercengine/storefront";

const sdk = createStorefront({
  storeId: "your-store-id",
  apiKey: "your-api-key",
  tokenStorage: new BrowserTokenStorage("myapp_")
});

async function authenticateUser() {
  // 1. Start with anonymous authentication
  const { data: anonData } = await sdk.auth.getAnonymousToken();
  
  // 2. User browses anonymously, adds items to cart
  await sdk.cart.createCart({
    items: [{ product_id: "product-123", quantity: 1 }]
  });
  
  // 3. User decides to login
  const { data: loginData } = await sdk.auth.loginWithPassword({
    email: "user@example.com", 
    password: "password"
  });
  
  // 4. SDK automatically updates tokens and maintains cart
  // No manual token management required!
}
```

### OTP Authentication Flow

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
async function otpLogin(phone: string) {
  // 1. Initiate OTP login
  const { data: otpData } = await sdk.auth.loginWithPhone({
    phone: phone,
    country_code: "+1",
    register_if_not_exists: true
  });

  if (!otpData) return;

  // 2. User enters OTP (from your UI)
  const otp = await getUserOTPInput(); // Your UI logic

  // 3. Verify OTP
  const { data: authData } = await sdk.auth.verifyOtp({
    otp: otp,
    otp_token: otpData.otp_token,
    otp_action: otpData.otp_action
  });

  // 4. Tokens are automatically managed
  if (authData) {
    console.log("User authenticated successfully!");
  }
}
```

### Multi-Environment Token Management

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
// Development/Staging/Production configuration
const getSDKConfig = () => {
  const isProduction = process.env.NODE_ENV === "production";
  
  return {
    storeId: process.env.NEXT_PUBLIC_STORE_ID!,
    environment: isProduction ? Environment.Production : Environment.Staging,
    apiKey: process.env.NEXT_PUBLIC_API_KEY!,
    
    tokenStorage: new CookieTokenStorage({
      prefix: isProduction ? "prod_" : "dev_",
      secure: isProduction,
      domain: isProduction ? ".mysite.com" : undefined,
      maxAge: isProduction ? 7 * 24 * 60 * 60 : 24 * 60 * 60 // 7 days prod, 1 day dev
    }),
    
    debug: !isProduction,
    
    onTokensUpdated: (accessToken, refreshToken) => {
      // Analytics or logging
      if (isProduction) {
        analytics.track("user_authenticated");
      }
    }
  };
};

const sdk = createStorefront(getSDKConfig());
```

## Token Lifecycle Events

### Handling Token Updates

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const sdk = createStorefront({
  storeId: "your-store-id",
  apiKey: "your-api-key",
  tokenStorage: new BrowserTokenStorage(),
  
  onTokensUpdated: (accessToken, refreshToken) => {
    // Called when:
    // - User logs in
    // - Tokens are refreshed automatically
    // - setTokens() is called manually
    
    console.log("Tokens updated");
    
    // Update your application state
    updateUserState({ authenticated: true });
    
    // Send to analytics
    analytics.identify(getUserIdFromToken(accessToken));
  },
  
  onTokensCleared: () => {
    // Called when:
    // - User logs out
    // - Tokens are invalid and can't be refreshed
    // - clearTokens() is called manually
    
    console.log("Tokens cleared");
    
    // Update your application state
    updateUserState({ authenticated: false });
    
    // Redirect to login
    router.push("/login");
  }
});
```

### JWT Utilities

The SDK provides utilities to extract information from tokens:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
// Get user information from current token
const userInfo = await sdk.getUserInfo();
// Returns: { userId: string, email?: string, customerId?: string, ... }

// Check authentication status
const isLoggedIn = await sdk.isLoggedIn();     // true if authenticated user
const isAnonymous = await sdk.isAnonymous();   // true if anonymous token

// Get specific user identifiers
const userId = await sdk.getUserId();
const customerId = await sdk.getCustomerId();
const customerGroupId = await sdk.getCustomerGroupId();
```

## Best Practices

### ✅ Production Recommendations

<Warning>
  **Always use automatic token management in production** with appropriate storage for your environment.
</Warning>

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
// ✅ GOOD: Production setup
const sdk = createStorefront({
  storeId: process.env.NEXT_PUBLIC_STORE_ID!,
  environment: Environment.Production,
  apiKey: process.env.NEXT_PUBLIC_API_KEY!,
  tokenStorage: new CookieTokenStorage({
    prefix: "myapp_",
    secure: true,
    sameSite: "Lax"
  }),
  onTokensUpdated: handleAuthSuccess,
  onTokensCleared: handleAuthFailure
});

// ❌ BAD: Manual management in production
const sdk = createStorefront({
  storeId: "store-id",
  apiKey: "api-key",
  // No tokenStorage = manual management
});
```

### Security Best Practices

1. **Use secure cookies in production**:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const tokenStorage = new CookieTokenStorage({
  secure: true,      // HTTPS only
  sameSite: "Lax",   // CSRF protection
  httpOnly: false    // Required for client access
});
```

2. **Environment-specific configuration**:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const isProduction = process.env.NODE_ENV === "production";

const sdk = createStorefront({
  // ... other config
  tokenStorage: new CookieTokenStorage({
    secure: isProduction,
    domain: isProduction ? ".mysite.com" : undefined
  })
});
```

3. **Handle token events properly**:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const sdk = createStorefront({
  // ... config
  onTokensCleared: () => {
    // Clear sensitive data
    clearUserCache();
    clearCartData();
    
    // Redirect to safe page
    router.push("/");
  }
});
```

### Framework Integration

For framework-specific token management patterns and implementation details, see our dedicated integration guides:

<CardGroup cols={2}>
  <Card title="React Integration" icon="react" href="/docs/sdk/react-integration">
    Context providers, hooks, and component patterns for React SPAs
  </Card>

  <Card title="Next.js Integration" href="/docs/sdk/nextjs-integration">
    SSR, Server Actions, and automatic cookie-backed token management
  </Card>

  <Card title="TanStack Start Integration" href="/docs/sdk/tanstack-start-integration">
    Server functions, route loaders, and pre-rendering
  </Card>

  <Card title="Astro Integration" href="/docs/sdk/astro-integration">
    SSR pages, API routes, middleware, and static prerendering
  </Card>

  <Card title="SvelteKit Integration" href="/docs/sdk/sveltekit-integration">
    Server load functions, form actions, hooks, and universal loads
  </Card>

  <Card title="Node.js Integration" icon="node-js" href="/docs/sdk/nodejs-integration">
    Server-side patterns and background job authentication
  </Card>
</CardGroup>

<Check>
  **Token Management Summary**: The SDK's automatic token management handles all the complexity of authentication, token refresh, and storage, allowing you to focus on building your application features while ensuring a seamless user experience.
</Check>
