Focuses on API authentication, access scopes, and permission management.
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
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
Solved! Go to the solution
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"})
}
}
}
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?
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.
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"})
}
}
}
honestly, i am new to shopify dev so, it could be that i miss understand how app proxy and other shopify components work
All good I'm just on my way home, give me about an hour and I can take a better look for you!
and I just want to confirm, with GraphiQL you can successfully save/update the metafield?
Yes, It worked when i used on the GraphiQL. Sorry I wasn't able to reply right away. I am catching a cold. haha
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