Automatically Refreshing Access Tokens
Learn how to automatically refresh access tokens for logged-in users in the Alokai Storefront and Unified SAP Integration
This guide is for Storefronts using SAP Commerce Cloud
If you are using another integration that has a different token renewal process, please refer to the documentation for that integration.
A common challenge in modern frontend applications is the security of the authentication process.
Among the many considerations in the selection process of solutions is the lifespan of a logged-in user's token. Some opt for very restrictive solutions with a short lifespan for the access token. But it's not a great user experience to have to reauthenticate often because your access token expires quickly.
In this guide, we'll implement automatic handling for renewing the access token for requests that fail due to this reason.
Prerequisites
- Alokai Storefront with the configured Middleware SDK Module
- Unified SAP Integration configured in the middleware
Base SDK Configuration
For reference, here is the standard starting configuration of the Alokai Starter's middlewareModule
.
// apps/storefront-unified-nextjs/sdk/options.ts
import type { CreateSdkOptions } from '@vue-storefront/next';
import { env } from 'next-runtime-env';
export function getSdkOptions() {
const apiUrl = env('NEXT_PUBLIC_ALOKAI_MIDDLEWARE_API_URL') ?? '';
const ssrApiUrl = env('NEXT_PUBLIC_ALOKAI_MIDDLEWARE_SSR_API_URL');
const cdnCacheBustingId =
env('NEXT_PUBLIC_ALOKAI_MIDDLEWARE_CDN_CACHE_BUSTING_ID') ?? env('GIT_SHA') ?? 'no-cache-busting-id-set';
const isMultiStoreEnabled = env('NEXT_PUBLIC_MULTISTORE_ENABLED') === 'true';
if (!apiUrl) {
throw new Error('NEXT_PUBLIC_ALOKAI_MIDDLEWARE_API_URL is required to run the app');
}
const options: CreateSdkOptions = {
middleware: {
apiUrl,
cdnCacheBustingId,
ssrApiUrl,
},
multistore: {
enabled: isMultiStoreEnabled,
},
};
return options;
}
Implementing the Token Refreshing Function
At a high level, the process of refreshing the access token involves creating a custom error handler that will attempt to refresh the access token when a request fails due to an unauthorized error.
The @vsf-enterprise/sapcc-sdk
package provides a function that handles the access token renewal process and retrying requests. This function is called createRefreshTokenAndRetryHandler
.
First, install the @vsf-enterprise/sapcc-sdk
package.
yarn add @vsf-enterprise/sapcc-sdk
Next, using the createRefreshTokenAndRetryHandler
function, create a refresh token handler using an errorHandler
config property.
If the request fails due to an unauthorized error, the error handler will call the refresh token handler to attempt to renew the access token and retry the request.
// apps/storefront-unified-nextjs/sdk/config.ts
import { createRefreshTokenAndRetryHandler } from '@vsf-enterprise/sapcc-sdk'; import { isSdkUnauthorizedError } from '@vue-storefront/sdk'; import { defineSdkConfig } from '@vue-storefront/next';
import type { UnifiedEndpoints } from 'storefront-middleware/types';
const handleRefreshTokenAndRetry = createRefreshTokenAndRetryHandler();
export function getSdkConfig() {
return defineSdkConfig(({ buildModule, config, getRequestHeaders, middlewareModule }) => ({
// ...
unified: buildModule(middlewareModule<UnifiedEndpoints>, {
apiUrl: `${sdkConfig.middlewareUrl}/commerce/unified`,
cdnCacheBustingId: config.cdnCacheBustingId,
defaultRequestConfig: {
headers: getRequestHeaders(),
},
errorHandler: async (context) => {
const { error, params, httpClient, config: errorHandlerConfig, url } = context;
return handleRefreshTokenAndRetry(error, () => httpClient(url, params, errorHandlerConfig), params, {
isUnauthorized(err) {
return isSdkUnauthorizedError(err) && err.message.includes('InvalidTokenError');
},
refreshTokenMethod: async () => {
await httpClient(`${config.middlewareUrl}/commerce/OAuthUserTokenRefresh`, []);
},
});
},
methodsRequestConfig: config.defaultMethodsRequestConfig.unifiedCommerce.middlewareModule,
}),
}));
}