Skip to main content

JWT Authentication

Storefront authentication uses a JSON Web Token (JWT) that expires. The theme must start the refresh interceptors of the FDK Store. Without the interceptors, an active shopper loses the session when the token expires.

The platform stores the token in a cookie. Any client outside the browser, such as a mobile application, must keep a cookie jar for the storefront to work.

Helper functions

Add these helpers to the utilities of the theme.

import { isRunningOnClient } from "./utils"; // Adjust the import path

/**
* Starts the JWT refresh interceptors.
*
* Conditions:
* - The code runs on the client.
* - The interceptors are not set yet.
*
* @param {Object} fpi - Fynd Platform Interface instance
*/
export function initializeJWTInterceptors(fpi) {
const state = fpi.store.getState();
const isInterceptorSet = state?.custom?.isInterceptorSet ?? false;
const jwtTokenRefreshThreshold = state?.custom?.jwtTokenRefreshThreshold ?? 120;

if (isRunningOnClient() && !isInterceptorSet) {
fpi.initialiseIntercetorsForJWTRefresh(jwtTokenRefreshThreshold);
}
}

jwtTokenRefreshThreshold is a number of seconds. The interceptor refreshes the token this many seconds before the token expires. The default value is 120.

A refresh can still fail, for example when the refresh token itself expired. Send the shopper to the login page in that case:

export const redirectToLoginOnRefreshTokenFail = (fpi) => {
if (isRunningOnClient()) {
const state = fpi.store.getState();
const refreshTokenEventListenerAdded =
state?.custom?.refreshTokenEventListenerAdded;
if (refreshTokenEventListenerAdded) return;

window.FPI.event.on("user.refreshTokenFailed", (error) => {
console.error("User refresh token failed:", error);
window.location.pathname = "/auth/login"; // Or another route
});

// Register the listener one time only
fpi.custom.setValue("refreshTokenEventListenerAdded", true);
}
};

The state flag prevents a duplicate listener on each navigation.

Integration

Call both helpers from pageDataResolver in lib.js:

import {
initializeJWTInterceptors,
redirectToLoginOnRefreshTokenFail,
} from "./utils"; // Adjust the import path

export async function pageDataResolver(pageResolverData) {
const { fpi } = pageResolverData;

// Start the JWT interceptors
initializeJWTInterceptors(fpi);

// Send the shopper to the login page if a refresh fails
redirectToLoginOnRefreshTokenFail(fpi);
}

Both helpers exit early on the server. It is safe to call them at the top of the resolver.

Verification

  1. Log in to the storefront.
  2. Keep the tab open until the token comes near its expiry time.
  3. Confirm in the network panel that a refresh call runs before the expiry.
  4. Confirm that the shopper stays logged in.
  5. Delete the refresh cookie and reload. Confirm that the theme opens the login page.

Was this section helpful?