Skip to main content

Customer sessions

The createCustomerSession function creates a server-only session that signs customers in and out with Shopify customer accounts. Use the session to check whether a customer is logged in, get an access token for Customer Account API requests, and run login, token refresh, and logout.

To serve the login, authorize, refresh, and logout routes, pass the session to createCustomerAccountServerHandlers.

Import createCustomerSession from @shopify/hydrogen/customer-account.

Create the session once at module scope.


Creates a customer session that signs customers in and out with Shopify customer accounts and manages their access tokens. Use the session on the server only.

The function throws when the shop ID, client ID, API URL, or timeout is invalid, when no fetch implementation is available, and when the function runs in a browser.

Anchor to input1
input1
required

The shop ID, the OAuth client ID, the authentication base URL, a custom fetch, and the token request timeout.

A customer session with methods for sign-in, the OAuth callback, access tokens, and logout.

Signs customers in and out with Shopify customer accounts, and gives your server their Customer Account API access tokens. Use the session on the server only.

Pass your session storage and the request context to each method. Each method makes the final response private and uncacheable.

Anchor to getAccessToken
getAccessToken
(sessionManager: , requestContext: ) => Promise<string>
required

Returns the customer's stored access token, or undefined when the token is missing or expired. The method never refreshes the token or writes to the session. Call getOrRefreshAccessToken() to refresh an expired token.

Anchor to getOrRefreshAccessToken
getOrRefreshAccessToken
(sessionManager: , requestContext: , options?: ) => Promise<string>
required

Returns a usable access token for the customer. When the stored token is missing or expired, the session gets new tokens from Shopify and writes them to your session storage. Call the method only where you commit the session to the response.

Returns undefined when the customer has no refresh token, or when a temporary refresh failure keeps the session for a retry. When Shopify rejects the refresh token with a 400 or 401 status, the session clears the stored tokens and returns undefined. Refresh failures never throw.

Anchor to handleOAuthCallback
handleOAuthCallback
(sessionManager: , requestContext: , request: Request) => Promise<string>
required

Completes sign-in from Shopify's OAuth callback request, saves the customer's tokens to your session storage, and returns the path to send the customer to. Commit the session to the response after the call.

The method throws CustomerAccountOAuthError when sign-in fails a check, and CustomerAccountApiError when the token request times out. After a failure, the customer needs to start sign-in again.

Anchor to isLoggedIn
isLoggedIn
(sessionManager: , requestContext: ) => Promise<boolean>
required

Returns true when the customer has a usable access token or a refresh token. The method never refreshes tokens.

Use the result for UI state, such as an account link. Gate Customer Account API data on an access token from getOrRefreshAccessToken().

Anchor to logout
logout
(sessionManager: , requestContext: , options?: ) => Promise<string>
required

Clears the customer's session data and returns the URL to send the customer to. Commit the session to the response after the call.

When the session has an ID token, the URL points to Shopify's logout endpoint with the post-logout URL attached. Without an ID token, the method returns the post-logout URL.

Anchor to prepareLoginUrl
prepareLoginUrl
(sessionManager: , requestContext: , options: ) => Promise<string>
required

Starts customer sign-in and returns the URL of Shopify's login page. Commit the session to the response, then redirect the customer to the URL.

The customer has 10 minutes to finish signing in. After that, the OAuth callback fails with the missing_pending_login code.

Examples

TypeScript

import type { ShopifyRequestContext } from "@shopify/hydrogen";
import {
createCustomerSession,
type ReadonlyCustomerSessionManager,
} from "@shopify/hydrogen/customer-account";

export const customerSession = createCustomerSession({
shopId: process.env.SHOP_ID!,
customerAccountApiClientId: process.env.PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID!,
});

const LOGIN_PATH = "/account/login?return_to=/account";

export async function getAccountRedirect(
request: Request,
sessionManager: ReadonlyCustomerSessionManager,
requestContext: ShopifyRequestContext,
) {
if (!(await customerSession.isLoggedIn(sessionManager, requestContext))) {
return LOGIN_PATH;
}

const accessToken = await customerSession.getAccessToken(sessionManager, requestContext);
if (!accessToken) {
// A refresh already ran for this visit. Send the customer to login to avoid a redirect loop.
if (new URL(request.url).searchParams.has("refreshed")) {
return LOGIN_PATH;
}
return `/account/refresh?return_to=${encodeURIComponent("/account?refreshed=1")}`;
}

return null;
}

Each session method takes a session manager that reads or writes your session storage. Pick the manager type by method:

  • isLoggedIn() and getAccessToken() only read the session and accept a read-only session manager.
  • getOrRefreshAccessToken(), prepareLoginUrl(), handleOAuthCallback(), and logout() write to the session and need a writable session manager.

Was this page helpful?