---
title: ID token claim import
description: >-
  Import customer data from third-party identity providers by mapping ID token
  claims to Shopify customer record fields.
source_url:
  html: 'https://shopify.dev/docs/api/customer-authentication/claim-import'
  md: 'https://shopify.dev/docs/api/customer-authentication/claim-import.md'
---

# ID token claim import

When customers authenticate through a third-party identity provider, you can automatically import their profile data from ID token claims into Shopify customer records. This eliminates the need for separate API calls to populate customer information.

***

## Requirements

* A [Shopify Plus](https://www.shopify.com/plus) plan
* A third-party identity provider [configured through the Shopify admin](https://help.shopify.com/en/manual/customers/customer-accounts/new-customer-accounts/identity-provider/connect)
* The identity provider must verify that the customer owns their email address and return an `email_verified` claim set to `true`

***

## How it works

During the [identity provider login flow](https://shopify.dev/docs/api/customer-authentication#third-party-identity-providers-idps), your identity provider returns an ID token containing claims about the customer. Shopify extracts supported claims from this token and writes them to the customer record. After authentication completes, the customer record is populated with the imported data.

Only `email` and `email_verified` are required for authentication. Validation of all other claims is silent and never blocks login. Claim import is all-or-nothing: when any claim fails validation, Shopify skips the entire import for that sign-in and the customer record keeps its previous values. Shopify retries the import on the customer's next sign-in and records each skipped import as an event on the customer's timeline in the Shopify admin. HTML content in any field is rejected to prevent cross-site scripting.

***

## Request the required scopes

Standard OIDC claims are only returned by your identity provider when the matching scope is requested during sign-in. Shopify requests `openid` and `email` by default. To import other standard claims, add the scopes they require to the **Additional scopes** field in the Shopify admin under **Settings** > **Customer accounts** > **Third-party identity provider**:

| Claim | Required scope |
| - | - |
| `given_name`, `family_name` | `profile` |
| `phone_number` | `phone` |
| `address` | `address` |

When you request a scope, your identity provider is permitted to return the claims that scope covers, and Shopify imports the [supported claims](#supported-claims) it recognizes. When you don't request a scope, the provider omits its claims and the matching customer fields are left unchanged. A sample **Additional scopes** value that requests every importable standard claim (along with a refresh token) is `profile phone address offline_access`.

### Userinfo backfill for skinny ID tokens

Some identity providers issue "skinny" ID tokens that omit standard profile claims to keep the token small, and instead expose those claims from the provider's `/userinfo` endpoint. When this happens, Shopify backfills the missing claims from `/userinfo`, so requesting the right scope is all you need to do — whether the provider delivers the claim in the ID token or from `/userinfo`.

The backfill follows a strict contract:

* **Scope-gated.** A claim is fetched and imported only when its OIDC scope (from the table above) is in your **Additional scopes**. Adding the scope is how you opt in.
* **The signed ID token always wins.** `/userinfo` fills only a claim that's blank or absent in the ID token. A value that's present in the signed ID token is never overwritten by `/userinfo`.
* **Provider-agnostic.** The backfill works for any third-party OIDC provider that has **Sync customer data** enabled and exposes a `userinfo_endpoint` in its discovery document. It isn't specific to any one provider.
* **Best-effort.** If the `/userinfo` request fails for any reason — an unreachable endpoint, a malformed response, or a subject that doesn't match the ID token — sign-in still succeeds. The customer is signed in without the enriched fields, and Shopify retries the backfill on their next sign-in.

Only `given_name`, `family_name`, `phone_number`, and the standard OIDC `address` are eligible for `/userinfo` backfill.

***

## Email and email verification

The ID token must include `email` and `email_verified`. Shopify uses the email to find an existing customer record or create a new one.

```json
{
  "email": "jane.doe@example.com",
  "email_verified": true
}
```

If `email_verified` is not `true`, the login is blocked and the customer sees an error page. The identity provider is responsible for verifying that the customer controls the email address before setting this claim to `true`.

***

## Configuration

In the identity provider settings in Shopify admin there are a few options that control how claim data is imported listed in the table below:

| Option | How claim data is imported |
| - | - |
| Sync customer data | Enables or disables claim import. When enabled, Shopify maps data from your identity provider's OIDC claims to customer fields on every sign-in. |
| Overwrite rules | Controls whether existing data is replaced. - **Do not overwrite existing customer data:** Only empty fields are updated.
- **Overwrite existing customer data:** Fields are updated with the latest values from the ID token on each login. |

***

## Supported claims

The following claims can be mapped from your identity provider's ID token to Shopify customer fields.

### Name

`given_name` and `family_name` map to the customer's first and last name. These are imported together and treated as a group. When overwriting, both values are replaced.

```json
{
  "email": "jane.doe@example.com",
  "email_verified": true,
  "given_name": "Jane",
  "family_name": "Doe"
}
```

### Phone number

`phone_number` maps to the customer's phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (`+16135551234`).

**An invalid phone number skips the whole import:**

A `phone_number` that isn't valid E.164 fails validation, which skips the entire import for that sign-in, including otherwise-valid claims like `given_name` and `family_name`. If your identity provider can't return an E.164 phone number, remove `phone` from the **Additional scopes** field so that Shopify can import the other claims.

```json
{
  "email": "jane.doe@example.com",
  "email_verified": true,
  "phone_number": "+16135551234"
}
```

### Address

`address` maps a single address to the customer record using the OIDC address claim field names:

* `street_address` → `address1`
* `locality` → `city`
* `region` → `province_code` (must be an [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) subdivision code like `ON` or `CA-ON`)
* `postal_code` → `zip`
* `country` → `country_code` (must be an [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code like `CA` or `US`)

**Note:**

Country and province values must be valid ISO codes. An address whose `country` doesn't resolve to an ISO code fails validation, which skips the entire import for that sign-in, as described in [How it works](#how-it-works).

```json
{
  "email": "jane.doe@example.com",
  "email_verified": true,
  "address": {
    "street_address": "789 Queen Street West",
    "locality": "Ottawa",
    "region": "ON",
    "postal_code": "K1A 0B1",
    "country": "CA"
  }
}
```

### Tags

The `urn:shopify:customer:tags` claim is a comma-separated string of tags. Tags are treated as a group. When overwriting, all existing tags are replaced with the values from the claim.

```json
{
  "urn:shopify:customer:tags": "vip, loyalty-gold, newsletter"
}
```

### Addresses

The `urn:shopify:customer:addresses` claim is an array of address objects that follows the [Admin API customer address](https://shopify.dev/docs/api/admin-graphql/latest/objects/MailingAddress) format. The `first_name`, `last_name`, and `phone` fields on each address are distinct from the customer-level `given_name`, `family_name`, and `phone_number` claims and can differ from them.

Addresses are treated as a group. When overwriting, all existing addresses are replaced with the values from the claim. Sending an empty array (`[]`) clears all addresses from the customer record.

```json
{
  "urn:shopify:customer:addresses": [
    {
      "address1": "123 Main Street",
      "address2": "Suite 400",
      "city": "Toronto",
      "company": "Acme Inc",
      "first_name": "Jane",
      "last_name": "Doe",
      "phone": "555-123-4567",
      "zip": "M5V 2H1",
      "province_code": "ON",
      "country_code": "CA",
      "default": true
    }
  ]
}
```

### Default address

When both the OIDC `address` claim and custom `urn:shopify:customer:addresses` are provided, Shopify determines the default shipping address using this priority:

1. If any custom address has `default: true`, that address is used.
2. If no custom address has `default: true`, the OIDC standard address becomes the default.
3. If only custom addresses are provided with no `default` flag, the first address in the array is used.

```json
{
  "address": {
    "street_address": "789 Queen Street West",
    "locality": "Ottawa",
    "region": "ON",
    "country": "CA"
  },
  "urn:shopify:customer:addresses": [
    {
      "address1": "123 Main Street",
      "city": "Toronto",
      "province_code": "ON",
      "country_code": "CA",
      "default": false
    },
    {
      "address1": "456 Oak Avenue",
      "city": "Vancouver",
      "province_code": "BC",
      "country_code": "CA",
      "default": true
    }
  ]
}
```

***

## Additional resources

* [OpenID Connect Core 1.0 — Requesting claims using scope values (§5.4)](https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims)
* [OpenID Connect Core 1.0 — Standard claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)
* [OpenID Connect Core 1.0 — Address claim](https://openid.net/specs/openid-connect-core-1_0.html#AddressClaim)
* [OpenID Connect Core 1.0 — UserInfo endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)

***
