Using the Customer Account API with Hydrogen
This tutorial creates a login button on a Hydrogen storefront that lets a customer authenticate using the Customer Account API and if successful, displays a welcome message with their email address.
What you'll learnAnchor link to section titled "What you'll learn"
After you've completed this tutorial, you'll be able to authenticate a Customer and make Customer Account API queries within a Hydrogen storefront.
RequirementsAnchor link to section titled "Requirements"
Step 1: Create login buttonAnchor link to section titled "Step 1: Create login button"
The first step is to create a simple login button in the your storefront. This button will route to the
/authorize endpoint which we will create in the next section.
Step 2: Create authorize routeAnchor link to section titled "Step 2: Create authorize route"
Visit the Hydrogen Customer Account API settings and note the Client ID under Customer Account API credentials. Shopify stores the client ID in the
.env file under
Also note the Authorization endpoint under Application Endpoints in the settings and use it as the
loginUrl to redirect the user to log them in.
While you're in the settings, add
http://localhost:3000/authorize or if using Oxygen, the auto-generated host as a Callback URI(s) under Application setup.
In your storefront, create an
authorize.tsx route under
/routes/ and fill out the
Step 3: Generate code challenge and verifierAnchor link to section titled "Step 3: Generate code challenge and verifier"
The previous step redirects the customer to the login page, but it isn't sufficient to authorize them. We need to add a Code Challenge and Verifier to the
Let's add the following code to
authorize.tsx. It will generate the verifier and code challenge then set them as parameters of the login request. We also store the verifier in the session for use in future steps.
Step 4: Add state and nonceAnchor link to section titled "Step 4: Add state and nonce"
In order to mitigate CSRF attacks, the use of the
state parameter is required. Optionally, you can also pass a
nonce parameter in order to mitigate replay attacks. Both are random values that you must generate and persist in your application.
Let's add the following code to
authorize.tsx to add our state and
nonce to the session and as parameters for the
Step 5: Decode nonceAnchor link to section titled "Step 5: Decode nonce"
Before we move on, let's add some code to
authorize.tsx that will aid us in retrieving the
nonce so we can compare it against the one we generated in the previous step.
Step 6: Fetch access tokenAnchor link to section titled "Step 6: Fetch access token"
The customer will be redirected to
redirect_uri upon completing authentication (in our case this is
/authorize). Let's add code to the
loader function to retrieve the
state parameters then fetch the
Back in the Hydrogen storefront's Customer Account API settings, we will note the Token endpoint under Application Endpoints and use it as the
tokenRequestUrl to request the access token.
We will verify that
state are returned and then we will request a token. A successful request will return the following values:
||A credential that authorizes a client application to access protected resources on behalf of a user. It will be used as part of token exchange to retrieve another
||The number of seconds until the access token expires.|
||a credential that allows a client application to obtain a new access token without requiring the user to reauthenticate. It will be used to retrieve a new
||JSON Web Token (JWT) that contains user identity information. Primarily used for logging out and verifying the
We will store these values in the session and verify the
Response codesAnchor link to section titled "Response codes"
You might encounter the following response codes:
||Remove padding (for example,
||Verify that the
Step 7: Token exchange for Customer Account APIAnchor link to section titled "Step 7: Token exchange for Customer Account API"
You can implement Token Exchange with the Customer Account API. This involves exchanging your previously received
access_token with that of the target application (the Customer Account API). You can add a new function to
authorize.tsx to exchange your storefront's
access_token in return for the Customer Account API's
Step 8: Query the Customer Account APIAnchor link to section titled "Step 8: Query the Customer Account API"
Now that we have the Customer Account API
access_token, we can start querying the API. In this example, we will display the customer's email address on the storefront if they login succesfully.
Let's move back to
_index.tsx that we created earlier and add a
loader function that checks for the existence of the Customer Account API
If it doesn't exist we return null, representing that a customer is not logged in; if it does exist then we can go ahead and query the API.
We first want to change
.env to include
CUSTOMER_API_VERSION with a value of
unstable. We can then make a POST request to the Customer Account API endpoint that includes an
Authorization header with the Customer Account API
customer_access_token in the session).
We will also change our template to accomodate the existance of a logged in customer.
Step 9: Log outAnchor link to section titled "Step 9: Log out"
Now that we can call the Customer Account API, let's close the loop by adding logout functionality.
Let's change the
_index.tsx template to add a welcome message when a user is logged in and a button to logout that points to a new
Now go back to the Hydrogen or Headless admin Customer Account API settings and note the Logout endpoint.
logout.tsx we define a
action function that clears out our private session and retrieves the
id_token. We then redirect the user to the Logout endpoint with an
id_token_hint parameter containing the
id_token we retrieved earlier.
When a user clicks logout, it will redirect the user to the
Logout URI defined in the Customer Account API settings. If no value is provided, it will redirect to shopify.com
Step 10: Refresh access tokenAnchor link to section titled "Step 10: Refresh access token"
access_token has a time of expiry defined by the
expires_in value that was returned in an earlier step. You can add some code to check if the
access_token is close to expiry and, if so, refresh it so the user doesn't experience any disruptions.
authorize.tsx to calcuate an
expires_at to keep track of when the
access_token will expire.
Next we move to
_index.tsx to add a
refreshToken function that will work similarly to Step 6: Fetch Access Token. In this case, the
grant_type will be
refresh_token and we add a
refresh_token parameter with the value received in the step above.
This will return a new set of
refresh_token to use next time.
Finally we add a
isLoggedIn function that will help us keep track of if a user is logged in and help us refresh the
access_token if we are getting close to the expiry time.
- Explore the GraphQL Customer Account API reference.
- Explore the full Customer Account API Example
- Learn how to Manage customer accounts with the Customer Account API