Skip to main content

Token Management

Why token management matters 🔐

Every storefront request to Elastic Path must carry a valid OAuth 2.0 access‑token in the Authorization header.
Because the shopper experience runs in the browser, the recommended flow is the implicit token grant: no client_secret travels to the client, yet the token still authorises catalog, cart, and checkout calls.
This guide shows how to obtain, persist, and reuse that token with the TypeScript Shopper SDK.

tip

For complete working implementations, check our Composable Frontend examples repository which includes ready-to-use patterns for:


1 · Generate an implicit shopper token

import { createAnAccessToken } from "@epcc-sdk/sdks-shopper";

const { access_token, expires_in } = await createAnAccessToken({
grant_type: "implicit",
client_id: process.env.CLIENT_ID, // safe in the browser
});

Returns
access_token – bearer string expires_in – seconds until expiry (default ≈ 3600)

info

client_id is public‑safe; it only identifies your application and carries no secret.

2 · Persist the token (three patterns)

PatternWhen to useSample code
localStoragePure SPA, needs persistence through refresh & tabs; beware XSS risks (Auth0 Community, Auth0)js\nlocalStorage.setItem('ep_implicit_token', access_token);\n
Readable cookieSEO‑friendly SSR where JS still needs token; set Secure; SameSite=Lax (Auth0 Community)js\ndocument.cookie = `ep_implicit_token=${access_token}; Path=/; Secure; SameSite=Lax`;\n
HttpOnly cookie (server)All API calls proxied through your server; maximises XSS safety (Auth0)ts\nres.setHeader('Set-Cookie', `ep_implicit_token=${access_token}; HttpOnly; Secure; Path=/`);\n
info

Complete examples on GitHub

warning

Security note: localStorage is vulnerable to XSS exfiltration; if you control a server layer, prefer an HttpOnly cookie

3 · Attach the token to every SDK call

import { client, listProducts } from "@epcc-sdk/sdks-shopper";

const token = localStorage.getItem("ep_implicit_token") ?? "";
client.setConfig({
baseUrl: "https://euwest.api.elasticpath.com",
headers: { Authorization: `Bearer ${token}` },
});

const products = await listProducts();

The header travels with each request as required

Using interceptors (alternative approach)

import { client } from "@epcc-sdk/sdks-shopper";

// Set up request interceptor to add token to all requests
client.interceptors.request.use(async (config) => {
const implicitToken = localStorage.getItem("ep_implicit_token") ?? "";
config.headers.Authorization = `Bearer ${implicitToken}`;
return config;
});

This approach is particularly useful when you need to dynamically retrieve the token for each request.

Managing both Implicit and Account tokens with interceptors

As described in the Authentication Concepts guide, many storefront experiences require both an implicit token and an Account Management Authentication token. The recommended approach is to use interceptors to handle both tokens:

import { client } from "@epcc-sdk/sdks-shopper";

// Set up request interceptor to add both tokens to all requests
client.interceptors.request.use(async (config) => {
// Add the implicit token for basic API access
const implicitToken = localStorage.getItem("ep_implicit_token") ?? "";
config.headers.Authorization = `Bearer ${implicitToken}`;

// Add account token for personalized shopper access, if available
const accountToken = localStorage.getItem("ep_account_token");
if (accountToken) {
config.headers["EP-Account-Management-Authentication-Token"] = accountToken;
}

return config;
});

This pattern ensures that:

  1. The implicit token is always sent (required for all API requests)
  2. The Account Management Authentication token is only sent when available
  3. Headers are updated dynamically with the latest tokens for each request
import { client, listCarts } from "@epcc-sdk/sdks-shopper";

export async function storefrontAPI(req, res) {
const token = req.cookies.ep_implicit_token;
client.setConfig({
baseUrl: "https://euwest.api.elasticpath.com",
headers: { Authorization: `Bearer ${token}` },
});

const carts = await listCarts();
res.json(carts);
}

4 · Token expiration and refresh

Tokens have limited lifespans and need to be refreshed periodically:

  • Implicit tokens expire in approximately 1 hour (3600 seconds)
  • Account Management tokens have configurable expiration times

There are two main strategies for handling token expiration:

  1. Proactive refresh - Refresh tokens before they expire
  2. Reactive refresh - Catch 401 errors and refresh tokens when needed

Here's a basic example of token expiration detection:

function isImplicitTokenExpired() {
const expiryTime = localStorage.getItem("ep_implicit_token_expiry");
if (!expiryTime) return true;

// Add buffer time (30s) to account for network latency
return Date.now() > parseInt(expiryTime) - 30000;
}

// When saving token, also save expiry time
function saveImplicitToken(access_token, expires_in) {
localStorage.setItem("ep_implicit_token", access_token);
// Calculate absolute expiry time
const expiryTime = Date.now() + expires_in * 1000;
localStorage.setItem("ep_implicit_token_expiry", expiryTime.toString());
}
info

For detailed token refresh strategies including proactive refresh, reactive refresh with 401 interceptors, and strategies for refreshing both implicit and account tokens, see the Token Refresh guide.

Summary

Proper token management is essential for creating secure and reliable Elastic Path storefronts. This guide has covered:

  1. Generating tokens - Using createAnAccessToken to get implicit and account tokens
  2. Storing tokens safely - Options for localStorage, cookies, or HttpOnly cookies
  3. Using tokens in requests - Setting up SDK interceptors to automatically include both tokens
  4. Token expiration basics - Understanding when and why tokens expire

By implementing these patterns and combining them with the refresh strategies from the Token Refresh guide, you'll ensure your storefront maintains secure authentication while providing personalized shopping experiences.