Skip to main content

Sign in with Shop

Add the <shop-login-button> web component to your self-hosted login page so Shop users can authenticate with their existing Shop account. The component renders the official button and initiates the OIDC authorization flow when clicked.

Developer preview

The Shop platform is in early access. Features and APIs may change before general availability.


In this guide, you'll learn how to do the following tasks:

  • Add the <shop-login-button> component to your login page.
  • Configure PKCE and redirect the user through the OIDC authorization flow.
  • Exchange the authorization code for tokens after the callback.

  • A Shop app with a client ID, client secret, and a configured redirect URI.
  • A server-side environment where you can securely handle the token exchange.

Anchor to Step 1: Add the ,[object Object], componentStep 1: Add the <shop-login-button> component

Load the <shop-login-button> script and add the component to your login page. Generate a state value and a PKCE code_verifier server-side, hash the verifier with SHA-256 to produce the code_challenge, then embed them as attributes.

HTML

<script type="module" src="https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.shop-login-button.esm.js"></script>

<shop-login-button
ux-mode="redirect"
client-id="YOUR_CLIENT_ID"
code-challenge-method="S256"
code-challenge="YOUR_CODE_CHALLENGE"
response-type="code"
scope="openid email"
redirect-uri="https://your-domain.com/auth/callback"
state="YOUR_STATE_VALUE"
analytics-context="loginWithShopSelfServe"
></shop-login-button>

Store the code_verifier and state in the user's session before the page loads; you'll need them to validate the callback.

Anchor to Component attributesComponent attributes

AttributeDescription
client-idYour client ID from the Dev Dashboard.
ux-modeSet to redirect to handle auth through page redirects.
code-challenge-methodSet to S256.
code-challengeYour PKCE code challenge (SHA-256 hash of the code_verifier).
response-typeSet to code for the authorization code flow.
scopeRequired: openid email. Add profile to also receive the user's name and picture.
redirect-uriYour callback URL, matching a redirect URI registered on your app.
stateA random, unguessable string to prevent CSRF attacks. Validate it in the callback.
analytics-contextSet to loginWithShopSelfServe.
borderedOptional. When present, adds a light border to the button.
full-widthOptional. When present, expands the button to fill its container width.

Anchor to Step 2: Handle the callbackStep 2: Handle the callback

When the user completes sign-in, Shop redirects to your redirect-uri with code and state query parameters. In your callback handler:

  1. Verify the state matches the value you stored in the user's session.
  2. Exchange the code for tokens by calling the token endpoint:

cURL

curl -X POST https://accounts.shop.app/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'client_id=YOUR_CLIENT_ID' \
--data-urlencode 'client_secret=YOUR_CLIENT_SECRET' \
--data-urlencode 'code=AUTHORIZATION_CODE' \
--data-urlencode 'code_verifier=YOUR_CODE_VERIFIER' \
--data-urlencode 'redirect_uri=https://your-domain.com/auth/callback'

The response includes an id_token (a signed JWT with identity claims like sub, email, and optionally name and picture), an access_token, and a refresh_token. Keep all three server-side and never expose them to the browser.


EndpointURL
Issuerhttps://accounts.shop.app
Discoveryhttps://accounts.shop.app/.well-known/openid-configuration
Authorizationhttps://accounts.shop.app/oauth/authorize
Tokenhttps://accounts.shop.app/oauth/token
UserInfohttps://accounts.shop.app/oauth/userinfo
JWKShttps://accounts.shop.app/auth/jwks

  • Store the sub claim from the id_token alongside your own user record to enable returning sign-ins without a full OIDC flow.
  • Exchange a consentToken for a user access token to read and write Shop User data. See Store metafields on Shop users.
  • Use the lead capture component to collect email addresses from users who aren't yet signed in.

Was this page helpful?