Join us for an upcoming Shopify Partner webinar on February 27, 2024. Discover the latest Checkout Extensibility features, and deep dive on improvements to Shopify Functions and Web Pixels. Register now for either the 10am EST or 2pm EST sessions.
Solved

Await Admin.Graphql(Query, Input ); HttpResponseError: Received An Error Response (401 Unauthorized)

WilsonNie
Shopify Partner
9 1 0

Hello I am using Remix app template with App Theme Extension and App Proxy . For some reason I am unable to authorized any Admin API call when my embedded app component  are being pressed.

 

Here is my endpoint file

 

export const action = async({request}) => {
    // param will get pass in like the following
    //  data = {product_id: 123}
    switch (request.method) {
        case "PUT": {
          /* handle "PUT" */
          // get the body data
          const data = await request.json()
          console.log(data)
          let query = `
          mutation MetafieldSet($metafields: [MetafieldsSetInput!]!) {
            metafieldsSet(metafields: $metafields) {
              metafields {
                key
                namespace
                value
                createdAt
                updatedAt
              }
              userErrors {
                field
                message
                code
              }
            }
          }
          `
          let input = {
            "metafields": [
              {
                "key": "wishlist",
                "namespace": "CP_app",
                "ownerId": "gid://shopify/Customer/7396475044125",
                "type": "json",
                "value": "{}"
              }
            ]
          }
          const { admin } = await authenticate.public.appProxy(request);
          const response = await admin.graphql(query, input );
          console.log(response)

          // append the data to the json metafield to a specific customer (likely by their id)
          // namespace: CP_app
          // key: wishlist
        //   console.log("request data", response)
          return json({"message": "item added"})
        }
        default: {
            return json({"message": "HTTP METHOD not suppported"})
        }
    }
}

 

Here is my Theme APP Extension test button file which is a liquid file

 

<button onclick="test()">test</button>


<script>
    function test() {
        console.log("hello")
        const fetchOptions = {
            method: "PUT",
            headers: {
            "Content-Type": "application/json",
            },
            body: JSON.stringify({"data": "value1"})
            
        };
        fetch("apps/cp-wishlist/wishlist/api/add-item", fetchOptions).then((data)=> data.json()
        ).then((x)=> {
            console.log(x)
            console.log("hello from fetch request")
        })
    }

</script>

{% schema %}
    {
      "name": "Test Button",
      "target": "section"
    }
{% endschema %}

 

 

Here is the output Log

WilsonNie_0-1706652029421.png

Anyone got an ideal why when the button being pressed the graphQL query is rejected due to authorization. but I've print out my admin object which contain my API keys and my API secret key

Accepted Solution (1)
WilsonNie
Shopify Partner
9 1 0

This is an accepted solution.

After testing stuff out,  I think the the token expired. so i have to create a new app in the Shopify Partner using the command 

npm run dev -- --reset

 Once the new app created and installed to your store. I am able to do a authorized GraphQL request. I make some changes due to i didn't understand how the syntax work. Here is the updated version which is working

export const action = async({request}) => {
    // param will get pass in like the following
    //  data = {product_id: 123}
    switch (request.method) {
        case "PUT": {
          /* handle "PUT" */
          // get the body data
          const data = await request.json()
          let metafields = [
              {
                "key": "wishlist",
                "namespace": "CP_app",
                "ownerId": "gid://shopify/Customer/7396475044125",
                "type": "json",
                "value": "{}"
              }
            ]
          
          
          let query = `mutation MetafieldSet($metafields: [MetafieldsSetInput!]!) {
            metafieldsSet(metafields: $metafields) {
              metafields {
                key
                namespace
                value
                createdAt
                updatedAt
              }
              userErrors {
                field
                message
                code
              }
            }
          }
          `
          const { admin } = await authenticate.public.appProxy(request);
          // console.log(admin.rest.session.accessToken)
          const response = await admin.graphql(query, {variables : {
            metafields
          }});
          console.log(response)

          // append the data to the json metafield to a specific customer (likely by their id)
          // namespace: CP_app
          // key: wishlist
          return json({"message": "item added"})
        }
        
        default: {
            return json({"message": "HTTP METHOD not suppported"})
        }
    }
}

 

 

View solution in original post

Replies 8 (8)

SomeUsernameHe
Shopify Partner
455 49 82

Try this:

export const action = async ({ request }) => {
  switch (request.method) {
    case "PUT": {
      const data = await request.json();
      console.log(data);

      const query = `
        mutation MetafieldSet($metafields: [MetafieldsSetInput!]!) {
          metafieldsSet(metafields: $metafields) {
            metafields {
              key
              namespace
              value
              createdAt
              updatedAt
            }
            userErrors {
              field
              message
              code
            }
          }
        }
      `;

      const input = {
        metafields: [
          {
            key: "wishlist",
            namespace: "CP_app",
            ownerId: "gid://shopify/Customer/7396475044125",
            type: "json",
            value: "{}",
          },
        ],
      };

      try {
        const { admin } = await authenticate.public.appProxy(request);
        const response = await admin.graphql(query, input);
        console.log(response);

        if (response.userErrors && response.userErrors.length > 0) {
          return json({ error: response.userErrors }, { status: 400 });
        }

        return json({ message: "item added", response });
      } catch (error) {
        console.error('GraphQL mutation error:', error);

        // Return the full error for debugging
        return json({ error: error.message, fullError: error }, { status: 500 });
      }
    }
    default: {
      return json({ message: "HTTP METHOD not supported" }, { status: 405 });
    }
  }
};


I have made a few adjustments, but mainly this will now print the full response/error and you might get something more specific than 401 unauthorized. Maybe this is a scope issue? 


Have I helped? Consider putting coffee in my mouth!
Buy Me a Coffee
WilsonNie
Shopify Partner
9 1 0

Thanks for the replay! unfortunately i am still getting the same response (maybe).  I've tested out the query using the GraphiQL, I think the Query itself it seem fine.  I do have write customer access so i don't think is a scope issues(maybe). Here is the new output log. 

WilsonNie_0-1706654471452.png

 

WilsonNie
Shopify Partner
9 1 0

This is an accepted solution.

After testing stuff out,  I think the the token expired. so i have to create a new app in the Shopify Partner using the command 

npm run dev -- --reset

 Once the new app created and installed to your store. I am able to do a authorized GraphQL request. I make some changes due to i didn't understand how the syntax work. Here is the updated version which is working

export const action = async({request}) => {
    // param will get pass in like the following
    //  data = {product_id: 123}
    switch (request.method) {
        case "PUT": {
          /* handle "PUT" */
          // get the body data
          const data = await request.json()
          let metafields = [
              {
                "key": "wishlist",
                "namespace": "CP_app",
                "ownerId": "gid://shopify/Customer/7396475044125",
                "type": "json",
                "value": "{}"
              }
            ]
          
          
          let query = `mutation MetafieldSet($metafields: [MetafieldsSetInput!]!) {
            metafieldsSet(metafields: $metafields) {
              metafields {
                key
                namespace
                value
                createdAt
                updatedAt
              }
              userErrors {
                field
                message
                code
              }
            }
          }
          `
          const { admin } = await authenticate.public.appProxy(request);
          // console.log(admin.rest.session.accessToken)
          const response = await admin.graphql(query, {variables : {
            metafields
          }});
          console.log(response)

          // append the data to the json metafield to a specific customer (likely by their id)
          // namespace: CP_app
          // key: wishlist
          return json({"message": "item added"})
        }
        
        default: {
            return json({"message": "HTTP METHOD not suppported"})
        }
    }
}

 

 

WilsonNie
Shopify Partner
9 1 0

honestly, i am new to shopify dev so, it could be that i miss understand how app proxy and other shopify components work

SomeUsernameHe
Shopify Partner
455 49 82

All good I'm just on my way home, give me about an hour and I can take a better look for you! 

Have I helped? Consider putting coffee in my mouth!
Buy Me a Coffee
SomeUsernameHe
Shopify Partner
455 49 82

and I just want to confirm, with GraphiQL you can successfully save/update the metafield?

Have I helped? Consider putting coffee in my mouth!
Buy Me a Coffee
WilsonNie
Shopify Partner
9 1 0

Yes, It worked when i used on the GraphiQL. Sorry I wasn't able to reply right away. I am catching a cold. haha

WilsonNie
Shopify Partner
9 1 0

after doing some reading, I am thinking the admin object is only work if you used it within the Admin Panel, If i want to make API request from my backend to Shopify API i would uses the `accessToken` inside of the admin object instead. but i could be wrong tho. here is the doc i was reading https://shopify.dev/docs/apps/auth/get-access-tokens/authorization-code-grant