Get JWT Session Token in Post-Purchase Extension

Solved
sofft-dev
Tourist
4 1 1

Hi there,

 

I'm having problems with authenticating API Requests to my App Backend. On the backend side I'm using the verifyRequest() Method from the @shopify/koa-shopify-auth package as recommended here: https://shopify.dev/apps/auth/session-tokens/how-session-tokens-work#anatomy-of-a-session-token

The problem I'm facing now is how to authenticate when making requests from my checkout post-purchase extension.

I thought I could use the token, that is sent from Shopify with the inputData object (Reference here). There is a token field that specifies a jwt session token - according to Shopify.

But when I append this token to the request I'm sending to my backend server, the server always responds with code 500 and the message "Session token had invalid API key".

 

Does somebody have an idea how to solve this problem? I am grateful for any kind of tips or solutions!

 

Thanks in advance!

 

Accepted Solution (1)

Accepted Solutions
sofft-dev
Tourist
4 1 1

This is an accepted solution.

This is not clean but try to save and pass the token in the ShouldRender step through storage.update(). Then, retrieve it in the Render step through storage.initialData. Hope this helps!

View solution in original post

Replies 3 (3)
cosoare
Tourist
5 1 0

I am facing a similar issue - I decoded the JWT token and it seems to be missing all the required keys as per the spec: https://shopify.dev/api/checkout-extensions/jwt-specification#claims

 

Wondering if anyone has managed to fix this or is this a bug?

sofft-dev
Tourist
4 1 1

This is an accepted solution.

This is not clean but try to save and pass the token in the ShouldRender step through storage.update(). Then, retrieve it in the Render step through storage.initialData. Hope this helps!

View solution in original post

cosoare
Tourist
5 1 0

Thanks for the reply!

 

What I am doing in the ShouldRender step is accessing the token from inputData, which is meant to be a JWT type token. Then I construct the headers based on this:

 

 

 

extend('Checkout::PostPurchase::ShouldRender', async ({inputData, storage}) => {

  const jwt_token = inputData.token;

  let response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer ' + jwt_token,
    },
    body: ...
  });
});

 

 

 

Making this request to my Rails backend throws an error like this:

 

 

[ShopifyApp::JWT] Failed to validate JWT: [ShopifyApp::JWT::InvalidAudienceError] 'aud' claim does not match api_key

 

 

 Digging through the JWT module I can see this comes from this line here, which leads me to believe something is wrong with the token. Now, inspecting the JS console I log the token and then use the https://jwt.io/ tool to decode the token, which in turn looks like the following & proves it's missing some object keys from the JWT spec, including the aud one which should be set as the API KEY:

 

Token Header is missing type: "JWT"

 

 

{
  "alg": "HS256"
}

 

 

 

Token Data 

 

 

{
  "iss": "shopify",
  "sub": "a3c59a6b3c451c33b90e68871cd944de",
  "input_data": {
    "extensionPoint": "Checkout::PostPurchase::ShouldRender",
    "initialPurchase": {
      "referenceId": "a3c59a6b3c451c33b90e68871cd944de",
      "customerId": 5788644180212,
      "destinationCountryCode": "GB",
      "totalPriceSet": {
        "shopMoney": {
          "amount": "25.98",
          "currencyCode": "GBP"
        },
        "presentmentMoney": {
          "amount": "25.98",
          "currencyCode": "GBP"
        }
      },
      "lineItems": [
        {
          "product": {
            "id": 6636284346612,
            "metafields": [],
            "title": "Fertilizer",
            "variant": {
              "id": 39467655692532,
              "metafields": [],
              "title": ""
            }
          },
          "quantity": 1,
          "totalPriceSet": {
            "shopMoney": {
              "amount": "19.99",
              "currencyCode": "GBP"
            },
            "presentmentMoney": {
              "amount": "19.99",
              "currencyCode": "GBP"
            }
          }
        }
      ]
    },
    "locale": "en",
    "shop": {
      "id": 1234,
      "domain": "mydomain.myshopify.com",
      "metafields": []
    },
    "version": "unstable"
  },
  "iat": 1642930977
}

 

 

 

I made a comparison with the token used for requests inside the Admin app and it's different:

{
  "alg": "HS256",
  "typ": "JWT"
}

 

{
  "iss": "https://myshop.myshopify.com/admin",
  "dest": "https://myshop.myshopify.com",
  "aud": "API_KEY",
  "sub": "71451279604",
  "exp": 1642934204,
  "nbf": 1642934144,
  "iat": 1642934144,
  "jti": "85c64eb0-2169-4bab-8760-4c2ceecdd6a7",
  "sid": "2fa37cd7fad96de5c965e75a8b8f159b11d11659326f93458471571cee7492e8"
}

 

 

 

The question is - what am I doing wrong or is the token specification not correct for the PostPurchase checkout?