Get Shop user information
After a user completes a Shop SDK authentication or lead capture flow, your app can read the information that the user authorized. The flow returns identity claims and a short-lived consent token. You exchange the consent token for a user access token, then use that token to make authenticated, user-scoped requests to the Shop Users API. In this guide, you'll turn a completed Shop SDK flow into an authenticated session that can read Shop user data.
Anchor to What you'll learnWhat you'll learn
In this guide, you'll learn how to:
- Capture the identity claims and consent token that a completed Shop SDK flow returns.
- Exchange the consent token for a user access token using the Shop Partners API.
- Understand how OAuth scopes and granted Rich Authorization Request (RAR) claims control the returned fields.
- Use the access token to read user-scoped data from the Shop Users API.
Anchor to RequirementsRequirements
- A Shop app with a client ID and client secret.
- A Sign in with Shop or lead capture integration with the Shop SDK. Both features can return the consent token.
- A trusted server where you can protect your client credentials and the user's tokens.
Anchor to Step 1: Get the consent token from a Shop SDK flowStep 1: Get the consent token from a Shop SDK flow
When a user completes the Shop SDK login or lead-capture feature, the flow can return identity claims and a signed shopConsentToken. The token is short-lived and represents the user's delegated consent to your app. The onComplete event carries this information:
| Field | Description |
|---|---|
email | The user's email address. |
emailVerified | Whether Shop verified the email address. |
consentedScopes | A space-separated list of the scopes the user consented to. |
signedIn | Whether the user signed in, as opposed to only providing their email address. |
shopConsentToken | The consent token to exchange for a user access token. |
JavaScript
Register the same onComplete handler on a lead-capture instance to exchange consent from that flow. Data requested with RAR isn't returned directly in the browser event. After the server exchanges shopConsentToken, the issued access token contains the granted RAR claims in its scope value.
A third-party identity provider integration signs users in and returns identity claims, such as sub and email, but it doesn't return a shopConsentToken. Use the Shop SDK login or lead-capture feature to exchange a consent token and call the Shop Users API.
Send the shopConsentToken only over HTTPS, exchange it from a trusted server, and don't log it. Don't construct a consent token yourself, and don't accept one from arbitrary input.
Send the shopConsentToken only over HTTPS, exchange it from a trusted server, and don't log it. Don't construct a consent token yourself, and don't accept one from arbitrary input.
Anchor to Step 2: Exchange the consent token for a user access tokenStep 2: Exchange the consent token for a user access token
From your server, call the fetchTokensForUser mutation on the Shop Partners API, authenticating with your client ID and client secret over HTTP Basic Authentication. The first exchange uses the consent token. Every later exchange uses the publicId that the first call returns.
Endpoint: https://shop.app/api/latest/partners/graphql.json
GraphQL Mutation
The user field returns the same user profile claims that the Shop Users API exposes, inline on the mutation response. Each field is gated by the issued token's scope: a field whose gating scope wasn't granted resolves to null, even if the response selects it. This lets you populate your user record from the mutation response without a follow-up call. The fields and their gating scopes are:
| Field | Gating scope or RAR claim |
|---|---|
sub | Always returned when the token authenticates a user. |
email, emailVerified | email (also granted by email:verified or user:manage). |
givenName | name or profile, or the granted given_name RAR claim. |
familyName | name or profile, or the granted family_name RAR claim. |
name | name or profile. |
phone | phone (also granted by phone:verified or user:manage), or the granted phone_number RAR claim. |
phoneVerified | phone (also granted by phone:verified or user:manage). |
birthdate | The granted birthdate RAR claim. |
avatar | avatar or profile. |
If the mutation fails, then user is null and userErrors is populated. A non-null user doesn't imply that any specific field resolved. Individual fields can still be null if the issued token didn't grant the required OAuth scope or RAR claim, or if the authorized value isn't on the user's profile.
For the first exchange, pass the consent token from Step 1:
GraphQL Variables
Persist the returned publicId against your own record of the user. After the first exchange, you won't need the consent token again. To mint a fresh access token later, call the same mutation with the stored publicId instead:
GraphQL Variables
Provide exactly one of consentToken or publicId per call.
Keep your client credentials and the returned access token server-side. Never expose them to the storefront, browser, Shopify Function, or Checkout UI extension, and never log the access token.
Keep your client credentials and the returned access token server-side. Never expose them to the storefront, browser, Shopify Function, or Checkout UI extension, and never log the access token.
Anchor to Step 3: Read user data from the Shop Users APIStep 3: Read user data from the Shop Users API
With the accessToken from Step 2, call the Shop Users API. The API is scoped to the authenticated user. Authenticate with Authorization: Bearer <accessToken>, not your client credentials.
Endpoint: https://shop.app/api/latest/users/graphql.json
Anchor to Read user profile fieldsRead user profile fields
Query the user field to read the authenticated user's profile claims. The same gating that applies to the user payload on fetchTokensForUser applies here. A field whose OAuth scope or RAR claim wasn't granted on the access token resolves to null.
GraphQL Query
If your access token doesn't authenticate a user, then the user query returns an Unauthorized error.
Anchor to Read app-owned metafieldsRead app-owned metafields
In addition to the user's profile, your app can read the metafields it owns on that user. Query them with the metafields query:
GraphQL Query
To read a single metafield by key, use the metafield query. The namespace defaults to your app's reserved namespace, so you only need the key:
GraphQL Query
You can read a user's identity information from either the user payload on fetchTokensForUser (Step 2) or the user query on the Users API (above). Both surfaces return the same fields and apply the same OAuth scope and RAR claim gating.
Access tokens expire after the number of seconds in expiresIn. When a token expires, call fetchTokensForUser again with the stored publicId to get a new one.
Anchor to Next stepsNext steps
- Store metafields on Shop users to write the custom data that you read here.
- Review the Shop Partners API and Shop Users API references.
- Add Sign in with Shop or lead capture to your storefront if you haven't already.