Skip to main content

Authenticate customers with the Customer Account API

A customer authentication flow lets customers securely log in to your app and access their account data through the Customer Account API. This tutorial shows you how to implement OAuth 2.0 with PKCE (Proof Key for Code Exchange)) to authenticate customers, store their access tokens, and query their order information.

You'll build a complete authentication system that generates security parameters, exchanges authorization codes for access tokens, and makes authenticated GraphQL queries to retrieve customer data.

In this tutorial, you'll learn how to:

  • Authenticate a customer with the Customer Account API.
  • Store authentication tokens securely in a database.
  • Query the Customer object from the Customer Account API.

Requirements

Development store

The development store should be pre-populated with test data, including an order associated with the email address you'll use to log in to the customer account experience.

Scaffold an app

Scaffold a React Router app that uses Shopify CLI.

Request access to Protected Customer Data

The Customer Account API requires access to Level 2 Protected Customer Data. Specifically access to first name, last name and email. Request access for your app.

Project

Anchor to Create database tables for authorization credentialsCreate database tables for authorization credentials

Set up your database to store PKCE values and customer access tokens—you'll need these tables to complete the OAuth flow and make authenticated API requests.

Anchor to Define Prisma schema for authorization credentialsDefine Prisma schema for authorization credentials

Create two models in prisma/schema.prisma. CodeVerifier stores temporary state and verifier values for PKCE flow, while CustomerAccessToken stores persistent access tokens for authenticating Customer Account API requests.

Anchor to Generate the database tablesGenerate the database tables

Run this migration command from your app's root directory to create the tables in your database:

Terminal

npx prisma migrate dev --name add_code_verifier_access_token

You should see a success message indicating your database is now in sync with your schema.

Anchor to Configure access scopes for your appConfigure access scopes for your app

Add the required access scopes to query customer data from the Customer Account API.

In your app’s shopify.app.toml file, include the customer_read_orders and customer_read_customers access scopes to display a customer’s information using the Customer Account API. In a production app, you might need to add other access scopes, depending on your use case.

Tip

Request access to protected customer data and ensure you've requested the Name and Email fields in your app configuration.

Anchor to Set up a tunnel URL and configure OAuth authenticationSet up a tunnel URL and configure OAuth authentication

Configure a public HTTPS domain for local development and set up Customer Account API authentication endpoints. The Customer Account API requires HTTPS and doesn't support localhost URLs.

Anchor to Create an ngrok tunnel with a static domainCreate an ngrok tunnel with a static domain

  1. Create an ngrok account.
  2. In your ngrok settings, add a static domain.
  3. Install the ngrok CLI.
  4. In a terminal, start ngrok using the following command:

Terminal

ngrok http --domain=<your-ngrok-domain> 3000

Anchor to Add Customer Account API authentication settingsAdd Customer Account API authentication settings

Add the [customer_authentication] module and <your-tunnel-url> to your shopify.app.toml file. This configures the OAuth 2.0 callback URL where customers return after authorization.

Tip

Your production app should discover authentication endpoints dynamically using discovery endpoints instead of hardcoding them.

Anchor to Generate the environment fileGenerate the environment file

  1. Run the following command to generate an .env file containing your app's environment variables:

Terminal

shopify app env pull
  1. Add your development storefront domain to this file and save:

Terminal

SHOP_STOREFRONT_DOMAIN=your-dev-store.myshopify.com
Note

Don't include https:// in the domain value.

Anchor to Initiate the OAuth authorization flowInitiate the OAuth authorization flow

Set up the authorization route to generate PKCE security parameters and redirect customers to Shopify's login page. This starts the secure OAuth flow for obtaining customer access tokens.

Anchor to Create the authorization route fileCreate the authorization route file

In your app's app/routes folder create a new file: customer-account-api.auth.jsx. This route handles the initial OAuth authorization request and generates the required security parameters.

Anchor to Fetch OpenID configuration dynamicallyFetch OpenID configuration dynamically

Retrieve the shop's OpenID configuration to get the authorization_endpoint URL. This endpoint points to Shopify's login page where customers authenticate.

Anchor to Define PKCE helper functionsDefine PKCE helper functions

Define helper functions to generate OAuth security parameters. These functions create a random code_verifier, compute its SHA256 code_challenge, and generate a state token for CSRF protection.

Anchor to Generate security parameters and store code verifierGenerate security parameters and store code verifier

Call the helper functions to generate the PKCE values, then save the code_verifier to your database using state as the lookup key. You'll retrieve this verifier in the callback handler to securely complete the token exchange.

Anchor to Redirect to Shopify's authorization endpointRedirect to Shopify's authorization endpoint

Construct the authorization URL with required OAuth parameters and redirect the customer to Shopify's login page. After authentication, Shopify redirects back to your callback URL with an authorization code.

Anchor to Configure session management for customer authenticationConfigure session management for customer authentication

Set up cookie-based session storage to persist customer login state across pages.

In your app's app folder, create a new file: sessions.server.jsx. This file provides helper functions that store and retrieve the customerTokenId in an encrypted, HTTP-only cookie. The cookie persists the customer's login state across pages in your app.

Anchor to Generate and store the customer access tokenGenerate and store the customer access token

Set up the OAuth callback handler to exchange the authorization code for a customer access token. This completes the PKCE flow and establishes an authenticated session for Customer Account API requests.

Anchor to Create the callback route fileCreate the callback route file

In your app's app/routes folder create a new file: customer-account-api.callback.jsx. This route handles Shopify's OAuth redirect after customer authentication.

Anchor to Extract authorization parameters from the callback URLExtract authorization parameters from the callback URL

Extract the code and state parameters from the callback URL. The code will be exchanged with your stored code_verifier for an access token, while state must match your original value to prevent CSRF attacks.

Anchor to Retrieve the stored code verifierRetrieve the stored code verifier

Query your database for the code_verifier (stored during authorization) using state as the lookup key. You'll need this verifier to securely exchange the authorization code for an access token in the next step.

Anchor to Fetch the token endpoint dynamicallyFetch the token endpoint dynamically

Discover the token endpoint by fetching the shop's OpenID configuration to retrieve the token_endpoint URL. This endpoint will be used to exchange your authorization code for an access token.

Anchor to Exchange code for a customer access tokenExchange code for a customer access token

Make a POST request to the token endpoint with your authorization code and code_verifier. This returns a customerAccessToken that authenticates all subsequent Customer Account API requests.

Anchor to Store access token and delete used code verifierStore access token and delete used code verifier

Store the customerAccessToken in your database along with its expiration time. After storing, delete the used code_verifier from the database to prevent replay attacks.

Store the tokenId in a session cookie and redirect the customer to your app's authenticated page.

Tip

For this tutorial, you'll redirect to an order list page, but in production you can choose any destination appropriate for your app.

Anchor to Query the Customer Account API with the customer access tokenQuery the Customer Account API with the customer access token

Set up an authenticated route that retrieves customer data from the Customer Account API. This demonstrates how to use the stored access token to make GraphQL queries on behalf of the authenticated customer.

Anchor to Create the order list route fileCreate the order list route file

In your app's app/routes folder, create a new file: customer-account-api.order-list.jsx. This route displays customer order data by querying the Customer Account API.

Anchor to Retrieve the customer token from sessionRetrieve the customer token from session

Get the customerTokenId from the session cookie. If no token is found, redirect the customer to authenticate.

Anchor to Fetch the access token from your databaseFetch the access token from your database

Fetch the customerAccessToken from your database using the tokenId as the lookup key. Verify the token exists and hasn't expired before proceeding with API requests.

Anchor to Discover the GraphQL API endpointDiscover the GraphQL API endpoint

Fetch the Customer Account API configuration to dynamically retrieve the graphql_api endpoint URL. This endpoint handles all Customer Account API GraphQL queries.

Anchor to Query the Customer Account APIQuery the Customer Account API

Send a POST request to the GraphQL endpoint with the customerAccessToken in the Authorization header. The API returns customer order data that's displayed on the order list page.

Use the Shopify CLI to preview your app to make sure that it works as expected.

  1. In a terminal, navigate to your app directory.
  2. Start app dev with your tunnel URL to build and preview your app.
shopify app dev --tunnel-url=https://<your-tunnel-url>:3000
  1. Select the dev store you declared as your SHOP_STOREFRONT_DOMAIN variable from the Generate the environment file step.
  2. Visit https://<your-tunnel-url>/customer-account-api/auth. You'll be redirected to the login page. After entering your email and one-time-passcode, you'll be redirected to a basic portal showing your customer name, email and orders.
Troubleshooting

Ensure the client_id matches the client_id in your shopify.app.toml file.

Anchor to Invalid redirect_uriInvalid redirect_uri

Ensure the [customer_authentication] module is included in your shopify.app.toml file and the redirect_uri matches the tunnel url. Do not use a local host URL or http.

Anchor to Invalid client credentialsInvalid client credentials

Ensure the test shop you've installed the app on matches the SHOP_STOREFRONT_DOMAIN in your .env file.

Anchor to Customer name is not displayedCustomer name is not displayed

Ensure you've requested access to Protected Customer Data and the name and email fields in your Dev Dashboard. Check your shopify.app.toml file for the required scopes.

Was this page helpful?