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.
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
Manual Token Management Simple approach where you handle token storage and refresh logic yourself
Automatic Token Management Production-ready approach with automatic token refresh, persistence, and cleanup
Manual Token Management
Perfect for prototyping, testing, or when you need full control over token handling.
Basic Setup
import { createStorefront } from "@commercengine/storefront" ;
const sdk = createStorefront ({
storeId: "your-store-id" ,
apiKey: "your-api-key" ,
// No tokenStorage provided = manual mode
});
Authentication Flow
Get anonymous token
const { data , error } = await sdk.auth. getAnonymousToken ();
if (data) {
// Manually set tokens
await sdk. setTokens (data.access_token, data.refresh_token);
}
Login with credentials
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);
}
Handle token refresh manually
// 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);
}
}
Manual Mode Methods
// 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
Basic Usage
With Callbacks
import { createStorefront }, { BrowserTokenStorage } from "@commercengine/storefront" ;
const sdk = createStorefront ({
storeId: "your-store-id" ,
apiKey: "your-api-key" ,
tokenStorage: new BrowserTokenStorage ( "myapp_" ) // Optional prefix
});
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.
}
});
Features:
✅ Persists across browser sessions
✅ Automatic token refresh
✅ Cross-tab synchronization
✅ Works with SPA frameworks (React, Vue, Angular)
Cookie Storage (SSR Compatible)
Basic Setup
Next.js Example
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"
})
});
// 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
})
});
Features:
✅ SSR/SSG compatible
✅ Server and client access
✅ Cross-subdomain sharing
✅ Automatic expiry handling
Memory Storage (Server-Side)
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:
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
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
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
// 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
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:
// 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
Always use automatic token management in production with appropriate storage for your environment.
// ✅ 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
Use secure cookies in production :
const tokenStorage = new CookieTokenStorage ({
secure: true , // HTTPS only
sameSite: "Lax" , // CSRF protection
httpOnly: false // Required for client access
});
Environment-specific configuration :
const isProduction = process.env. NODE_ENV === "production" ;
const sdk = createStorefront ({
// ... other config
tokenStorage: new CookieTokenStorage ({
secure: isProduction,
domain: isProduction ? ".mysite.com" : undefined
})
});
Handle token events properly :
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:
React Integration Context providers, hooks, and component patterns for React SPAs
Next.js Integration SSR, Server Actions, and automatic cookie-backed token management
TanStack Start Integration Server functions, route loaders, and pre-rendering
Astro Integration SSR pages, API routes, middleware, and static prerendering
SvelteKit Integration Server load functions, form actions, hooks, and universal loads
Node.js Integration Server-side patterns and background job authentication
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.