Trouble authenticating app proxy request in remix

Hello,

I am a Shopify dev newbie, and I am having trouble authenticating the app proxy request coming in from my theme app extension.

In my app.new.tsx file i have the following loader function that tries to replicate similarly what the docs say from
https://shopify.dev/docs/api/shopify-app-remix/v1/authenticate/public/app-proxy

loader function is:

export const loader = async ({ request }) => {
await authenticate.admin(request);
console.log(“hello from loader”);
try {
const { admin, session, liquid } = await authenticate.public.appProxy(
request
);

if (session && session.shop) {
const titleFromDb = await getBlockTitle();
console.log("title is: ", titleFromDb);
return json({ blockTitle: titleFromDb });
} else {
return json({ error: “Authentication failed.” }, { status: 403 });
}
} catch (error) {
console.error(“Error in loader:”, error);

// Check if error is an instance of Error
if (error instanceof Error) {
return json({ error: error.message }, { status: 500 });
} else {
return json({ error: “An unknown error occurred.” }, { status: 500 });
}
}
};

And in my theme app extension in the liquid code i have the following code to make the fetch call to the app proxy to communicate with my remix app:

When i try to use it all i keep getting a 404 error and sometimes a 400 error along with a log saying the query does not contain a signature value. I am really confused about how this is all supposed to be set up and I am using ngrok for the tunneling for the app proxy.

Error from server log:

16:01:06 │ remix │ [shopify-app/INFO] Authenticating admin request
16:01:07 │ remix │ Error in loader: NodeResponse [Response] {
16:01:07 │ remix │ size: 0,
16:01:07 │ remix │ [Symbol(Body internals)]: {
16:01:07 │ remix │ body: null,
16:01:07 │ remix │ type: null,
16:01:07 │ remix │ size: 0,
16:01:07 │ remix │ boundary: null,
16:01:07 │ remix │ disturbed: false,
16:01:07 │ remix │ error: null
16:01:07 │ remix │ },
16:01:07 │ remix │ [Symbol(Response internals)]: {
16:01:07 │ remix │ url: undefined,
16:01:07 │ remix │ status: 400,
16:01:07 │ remix │ statusText: ‘Bad Request’,
16:01:07 │ remix │ headers: {},
16:01:07 │ remix │ counter: 0,
16:01:07 │ remix │ highWaterMark: undefined
16:01:07 │ remix │ }
16:01:07 │ remix │ }
16:01:09 │ remix │ [shopify-app/INFO] Authenticating app proxy request
16:01:09 │ remix │ [shopify-app/INFO] Query does not contain a signature value.

My app proxy config in shopify partners is like this:
subpath prefix: apps
subpath: boostbundle
proxy url: https://7d0e-97-116-185-30.ngrok-free.app/app/new

I have that proxy url set up assuming it’s supposed to communicate with my app.new.tsx file

Where am i going wrong in all of this. Any help would be greatly appreciated!!

Hi Hacun3jr,

From the error logs and the code you have shared, it seems there could be an issue with how the request is being authenticated. The error Query does not contain a signature value suggests that the request is not being properly signed or the signature is not being included in the request sent from your app to Shopify.

When you make a request to your app proxy, Shopify signs the parameters and includes the signature in the request. Your app should then compare this signature with a hash of the parameters to authenticate the request. If the signature is missing or does not match the hash, you will get the Query does not contain a signature value error.

Here are a few things you could check or try:

  1. Check how you are generating the signature: Make sure you are correctly generating the signature on your server and including it in the request. The signature should be a hash of your app’s shared secret and the sorted request parameters.

  2. Check your shared secret: Make sure the shared secret you are using to generate the signature is correct. You can find the shared secret in your app settings in the Shopify Partners Dashboard.

  3. Check the request parameters: Ensure that the request parameters you are using to generate the signature match exactly with the parameters Shopify includes in the request. They should be sorted in lexicographical order (alphabetical order).

  4. Check your app proxy configuration: Make sure that the app proxy URL and the subpath you have configured in the Shopify Partners Dashboard matches with the URL and path you are using in your app.

Try the above and let us know if your still seeing issues.

Hello Hacun3jr,

I figure out problem you want to show your data on publicly, but you add admin auth when you remove this line await authenticate.admin(request**);** code is working, same issue i stuck, I figured out this promblem hope this is helps you.

I was wondering if you could expand on this a little bit more? I’m having the same issue with my code:

location.tsx:

import { json } from "@remix-run/node";
import { authenticate } from "../shopify.server";
import type { LoaderFunction } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";

export const loader: LoaderFunction = async ({ request }) => {
  const { admin } = await authenticate.public.appProxy(request);

  const response = await admin?.graphql(
    `#graphql
    query Locations {
      locations(first: 10) {
        edges {
          node {
            id
            name
            address {
              address1
              address2
              city
              country
              province
              zip
            }
          }
        }
      }
    }`
  );
  try {
    const locationData = await response?.json();
    return json({ data: locationData })
  } catch (error) {
    console.error(error); // Log the error for server-side debugging
    return json({ error: "Failed to fetch locations", err: error }, { status: 500 });
  }
}

export default function Location() {
  const response = useLoaderData

Thanks!

Hello,

import { authenticate } from “../shopify.server”;
import prisma from ‘../db.server’;

export async function loader({ request, params }) {
try {
const shopy = await authenticate.public.appProxy(request);
const allModels = await prisma.session.findMany({
where: {
shop: { equals: shopy.session.shop}
},
});
const setting = await prisma.[tablename].findFirst({
where: { shopid: shopy.session.shop }
});
return {
data: JSON.stringify(setting),
};
} catch (error) {
console.error(error);
return {
status: 500,
data: ‘An error occurred while fetching data.’,
};
} finally {
await prisma.$disconnect();
}
}

Can you tell me why I’m getting a 404 error when trying to make a request from my theme app extension

Here is my App proxy config
[app_proxy]
url = “https://rivers-sin-resistant-bigger.trycloudflare.com/app/ClientRequests
subpath = “proxy943”
prefix = “apps”

this is my app.ClientRequests route,

import shopify from “../shopify.server”;
export async function action({request, params}) {
const { admin } = await shopify.authenticate.public.appProxy(request);
const formData = await request.formData();
const productData = Object.fromEntries(formData);
const variantId = productData.productId;
const response = await admin.graphql( { node(id: "${variantId}") { ... on ProductVariant { id sku title price product { id title description handle featuredImage { height url altText } } } } });

const jsonResponse = await response.json();
return new Response(JSON.stringify(jsonResponse), {
status: 200,
headers: {
‘Content-Type’: ‘application/json’,
},
});
}

why would I get a 404 error?

Shouldn’t the signature be auto generated?

The problem with this approach, is that you cannot expose the admin variable, and therefore cannot use methods like:

admin.graphql()

Even when I use the correct app proxy authentication:

const { admin } = await authenticate.public.appProxy(request);

Can you show us, how you resolved this?

Can you please share a link on how to sign a request.