This document describes how [JWTs (JSON web token)](https://jwt.io/) need to be structured in order to be used in post-purchase app extensions on the Shopify checkout. It describes the claims that can be used, and whether they're optional. ## Overview The data passed from Shopify to the extension point is signed with a shared secret ([JWT](https://jwt.io/)). When you make a call to your backend server, you can use this secret to verify that the request came from Shopify. The following example displays how you can use a changeset token to request changes to an initial purchase: <p> <div class="react-code-block" data-preset="basic"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar basic-codeblock"></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="js"> RAW_MD_CONTENTextend('Checkout::PostPurchase::Render', async (root, input) => { const buyNowButton = root.createComponent(Button, { onPress() { const changeset = await fetchChangeset(input); input.applyChangeset(changeset.token); }, }); const pagePayload = input.storage.initialData; buyNowButton.appendChild(`Buy "${pagePayload.variantTitle}" now!`); root.appendChild(buyNowButton); root.mount(); }); // this call would ideally fetch all available changesets at once, instead // of one at a time const fetchChangeset = async (input) => { const request = await fetch('https://example.com/fetch-changeset', { method: 'POST', body: JSON.stringify({ initialPurchase: input.initialPurchase.token }), }); return request.json(); }; END_RAW_MD_CONTENT</script> </div> </p> If your app makes a return call to your extension point, then you must sign `applyChangeset` with the shared secret. Shopify will use the secret to verify that the request is coming from your app. ## Encoding and decoding JWTs can be encoded and decoded by using the client secret of an app as the token key, and by setting the hashing algorithm to HS256. **Ruby example:** ``` ruby JWT.encode(payload, api_secret, 'HS256') ``` ## Claims ### JWT ID (JTI) Used to make sure each token is unique, and prevent potential replay attacks. - **Shopify issued token:** Not present. - **Partner issued token:** Required. It is strongly recommend to use UUIDs, to ensure each token is [unique](https://stackoverflow.com/questions/1155008/how-unique-is-uuid#answer-1155027). ### Issuer (ISS) Used to identify who issued the token. - **Shopify issued token:** Always present, and statically set to "shopify". - **Partner issued token:** Required. The `api_key` of the app issuing the token. ### Subject (SUB) The reference ID of the initial purchase the token was issued for. - **Shopify issued token:** Always present. - **Partner issued token:** Required. ### Issued at time (IAT) Used to identify when the token was generated. - **Shopify issued token:** Always present. - **Partner issued token:** Required. >Note: As a security measure, changesets signed before the initial purchase is completed aren't accepted. ### Expiration time (EXP) Used to prevent a token from being used after a certain time. - **Shopify issued token:** Not present. - **Partner issued token:** Optional. ### Not before time (NBF) Used to prevent a token from being used before a certain time. - **Shopify issued token:** Not present. - **Partner issued token:** Optional. ### Audience (AUD) Unused.