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.
Anchor to What you'll learnWhat you'll learn
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
Customerobject from the Customer Account API.
Requirements
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.
You'll need to use the latest version of Shopify CLI.
Scaffold a React Router app that uses Shopify CLI.
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
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.
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
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.
Request access to protected customer data and ensure you've requested the Name and Email fields in your app configuration.
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
- Create an ngrok account.
- In your ngrok settings, add a static domain.
- Install the ngrok CLI.
- In a terminal, start ngrok using the following command:
Terminal
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.
Your production app should discover authentication endpoints dynamically using discovery endpoints instead of hardcoding them.
Your production app should discover authentication endpoints dynamically using discovery endpoints instead of hardcoding them.
Anchor to Generate the environment fileGenerate the environment file
- Run the following command to generate an
.envfile containing your app's environment variables:
Terminal
- Add your development storefront domain to this file and save:
Terminal
Don't include https:// in the domain value.
Don't include https:// in the domain value.
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.
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 Open ID 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.
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.
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.
For this tutorial, you'll redirect to an order list page, but in production you can choose any destination appropriate for your app.
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 Graph QL 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.
Anchor to Preview the appPreview the app
Use the Shopify CLI to preview your app to make sure that it works as expected.
- In a terminal, navigate to your app directory.
- Start
app devwith your tunnel URL to build and preview your app.
- Select the dev store you declared as your
SHOP_STOREFRONT_DOMAINvariable from the Generate the environment file step. - 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
Anchor to Invalid client_idInvalid client_ id
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.
Anchor to Tutorial complete!Tutorial complete!
Congratulations! You've built a Customer Account API authentication flow using OAuth 2.0 with PKCE. Keep the momentum going with these related tutorials and resources.
Anchor to Next stepsNext steps
Explore the GraphQL Customer Account API reference.
Manage customer accountsLearn how to manage customer accounts with the Customer Account API.
Hydrogen's Customer Account API implementationExplore the createCustomerAccountClient reference, including storefront usage examples.