/auth/login 404 with shopify app proxy

Topic summary

Core Issue:
Developers are encountering a 404 error when implementing Shopify app proxy authentication, specifically with the /auth/login endpoint. The error appears when following tutorial implementations, particularly one by Di Stephano.

Root Causes Identified:

  • Incorrect proxy URL configuration in shopify.app.toml file
  • Mismatched route file naming (must align with proxy URL path)
  • Issues with the loader function when trying to access admin and session objects during authenticate.public.appProxy(request)

Working Solution (from arifkpi):

  • Configure proxy settings in shopify.app.toml with proper URL, subpath, and prefix
  • Create route file matching the proxy URL structure (e.g., app.proxy.jsx for /app/proxy endpoint)
  • Use relative URLs in frontend fetch requests (/apps/{subpath})
  • In the loader function, only destructure { liquid } from the authentication call initially, avoiding admin and session which cause errors
  • Return liquid template for rendering

Additional Recommendations:

  • Deploy to hosting service (Render.com suggested) early in development to avoid local environment issues
  • Ensure environment variables are properly configured in both local .env and production hosting
  • Use loader for GET requests and action for POST/PUT/DELETE operations

Status: Multiple users confirmed the solution works after implementing the corrected configuration and avoiding problematic object destructuring.

Summarized with AI on November 6. AI used: claude-sonnet-4-5-20250929.

I followed a YT video on how to set up an app proxy. I also looked at a lot of Shopify forum posts to no avail
I get this error in the dev tools console (I think the Youtuber deleted my comment when I tried asking about this error)
GET https://testingwishlist.myshopify.com/auth/login 404 (Not Found)

and this from my terminal
GET /app/proxy/?shop=testingwishlist.myshopify.com&logged_in_customer_id=&path_prefix=%2Fapps%2Fproxytest&timestamp=1718050314&signature=819a839
ceb80bf73ef9b978ad39c7ddcf7324744ea00b4d06710ffefb5cbff4f 302

Here is my proxy.liquid and my proxy.js

<body>
    <button onclick="testProxy()">test proxy</button>
</body>

<script async src={{ "proxy.js" | asset_url }} defer></script>

{% schema %}
{
  "name": "Proxy Embed",
  "target": "section",
  "settings": [
    {
      "type": "header",
      "content": "Proxy button to customer wish list"
    }
  ]
}
{% endschema %}
function testProxy() {
    return new Promise((resolve, reject) => {
        fetch("https://testingwishlist.myshopify.com/apps/proxytest"), {
            method: 'POST',
            redirect: 'manual',
            headers: {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*',
            }
        }
    }).then((response) => {
        console.log(response, 'response');
    }).then((data) => {
        resolve(data)
    }).catch((error) => {
        reject(error)
    })
}

Here is my app.proxy.jsx which is in the routes folder

import { authenticate } from '../shopify.server'
import { Page } from '@shopify/polaris'
import { cors } from 'remix-utils'
import { json } from '@remix-run/node';

export const loader = async ({request}) => {
    console.log('---hit app proxy----')

    const {session} = await authenticate.public.appProxy(request)
    
    return await cors(request, json({status: 200}))
}

const Proxy = () => {
    return <Page>proxy </Page>
}

export default Proxy

The console.log in my app.proxy.jsx does turn up in the terminal along with the error, so I at least know that its connected to the fetch in proxy.js

My App proxy settings in Shopify Partner is :
Subpath prefix: apps
Subpath: proxytest
Proxy URL: https://journalists-attribute-slim-paste.trycloudflare.com/app/proxy
The URL changes each time I restart the app from the terminal, so I always make sure to update the Proxy URL

The App Proxy Url from the admin settings is: https://testingwishlist.myshopify.com/apps/proxytest

I did add this to my remix.config.js file but it didn’t change anything

serverDependenciesToBundle: [
    /^remix-utils.*/,
  ],
1 Like

I’m getting this error too! is this Di Stephano’s tutorial hahah? Do you have hosting setup on yours, I’m thinking it might have to do with how my app is built up to fly.io. But I’m not sure. I’m getting a 404 error on my proxy GET, same as you

I don’t have a dedicated hosting setup, just been using application_url from the .toml file for my proxy url

Maybe try adding this under the [webhooks] section in the shopify.app.toml ?

[app_proxy]
url = "yourcloudflarelink.com"
subpath = "yoursubpath"
prefix = "apps"

This from someone in the discord server where they actually have their proxy url only set with the main directory. Unlike the video where he does the full proxy app url.

here’s the discord discussion. https://discord.com/channels/597504637167468564/1251292194631843952

I’ll be trying out and debugging more tomorrow

I just looked and my shopify.app.toml file already has that section in there. I think it auto updates whenever I restart the server.

gotcha, gotcha. Yeah so the discord steps didn’t fix anything? I can try messaging the guy on discord to see if he has an example

Hope it will help someone in future.

I’m able to successfully fetch data using App Proxy, I followed Di Stephano’s tutorial initially but there was some issue. So I need to do some adjustments.

The first thing I did is use “shopify.app.toml” file to put the proxy settings because it will auto update the URL as needed. Example code I put there:

start of code

[app_proxy]
url = “https://base-jewelry-dayton-hold.trycloudflare.com/app/proxy
subpath = “styledata”
prefix = “apps”

end of code

Explanation
As the URL is “https://base-jewelry-dayton-hold.trycloudflare.com/app/proxy”, so I need to create a file on “routes” folder name “app.proxy.jsx”, so it will match with the URL on the backend.

For the frontend, it will be like: my-store-url/{prefix}/{subpath}, so something like that: https://my-store-url.myshopify.com/apps/styledata

So now I can send a request by like that, I put the URL relative so it will match with store URL:

start of code

Request Data

end of code

And finally code for the backend (app.proxy.jsx)

// start of code

import db from “../db.server”;
import { authenticate } from “../shopify.server”;
import { json } from “@remix-run/node”;

export const loader = async ({ request }) => {
const { admin, session } = await authenticate.public.appProxy(request);
const shopData = await admin.rest.resources.Shop.all({ session: session });
const shopId = shopData?.data[0].id;

const styler = await db.styler.findFirst({
where: {
storeId: shopId.toString(),
},
});

const response = json({
ok: true,
message: “Success”,
data: styler,
});

return (request, response);
};

end of code

I’m using a loader because I need to fetch the data, if you need POST/PUT/DELETE etc you need to use action then.

And finally I’m getting the data the attached screenshot.

1 Like

oh wow! Thank you so much @arifkpi for the code sample and assist! Do you happen to have the app pushed to the partner store, or are you running the app locally with ‘npm run dev’?

I setup a new test app to follow your setup, but I’m still hitting 500 errors. This is in context of running the app locally with ‘npm run dev’. It looks like this discussion was maybe relevant for the error we’re still seeing, but I’m not too sure after seeing your screenshots that its working on your machine: https://community.shopify.com/c/online-store-and-theme/application-proxy-there-was-an-error-in-the-third-party/td-p/529794

Thanks again!

I think I was able to get it, and it may have something to do with my access_scopes in shopify.app.toml file? What access scopes are you using @arifkpi ? I currently have: read_customers,read_products,write_customers,write_products

Hey! it worked. Thank you.

For the app I’m working on, I don’t need any shop/customer data; for that reason, access_scopes is empty in my config.

The 500 error code indicates that there is a server error. I think your proxy code contains an error; please double-check the code because I got the same error as well when my code was faulty.

hey did you use shopify’s implementation of AuthenticateAppProxy?

from my snippets above and OP’s we’re using this method:

authenticate.public.appProxy()

this is with the Remix app template with jsx

https://shopify.dev/docs/api/shopify-app-remix/v1/authenticate/public/app-proxy

1 Like

if you don’t mind, I noticed you also are utilizing npm run dev. Im in early stages of development so im wondering how my .env would get read. is there a common method of passing the environment variables in development? ive been looking everywhere

thank you for getting back this quick btw

no problem! as for envs, for local dev you basically use the shopify.app.toml and the .env file that gets created after your initial:

shopify app init

I’d also say, even if you’re just in dev/test stage, definitely move your app up to it’s hosting service. It’ll ensure that your connection to the app hosting and the basic default app is working with the env configurations. I ran into hiccups during those steps, and it would’ve saved us so much time just making sure things were squared away then.

Your App Hosting service usually has a way to config envs. I use Render.com for app hosting as they have a free development tier (if you notice your app is down, you’ll have to manually spin it back up on the free tier). I also believe Render became a new partner with Shopify recently in the last couple of months. We previously used Fly.io and often had issues with spin-up, Render was seamless.

https://docs.render.com/deploy-shopify-app

lmk if anything else, best of luck.

Believe it or not, I’ve been in a one month hiccup after changing from .NET to React Remix for Shopify Development. I feel like if you took a quick look at my issue you may have solved this many times by now:

Essentially, we leverage a static ngrok_domain.

made my app proxy settings as

url: shopifystore.com/app/api

prefix: apps

subpath: member

Prior to this I created app.api.jsx, and I’m currently seeing the shopify 404 page with the url as (auth/login) despite the fact I authenticated the proxy request (or so I assume..).
my app.api.jsx :

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

export const loader = async ({ request }) => {
  // Parse the URL to extract query parameters
  const url = new URL(request.url);

  // Get query parameters from the URL
  const shop = url.searchParams.get("shop");
  const signature = url.searchParams.get("signature");
  const timestamp = url.searchParams.get("timestamp");

  console.log("Incoming Query Parameters:");
  console.log("Shop:", shop);
  console.log("Signature:", signature);
  console.log("Timestamp:", timestamp);

  // Check if the required parameters are missing
  if (!shop || !signature) {
    console.log("Missing required parameters.");
    return json({ error: "Missing required parameters" });
  }

  try {
    // Authenticate the app proxy request
    const { admin, session} = await authenticate.public.appProxy(request);

    // Log success
    console.log("Authentication successful:", { shop, session });

    // Respond with success
    return json({
      ok: true,
      message: "App Proxy Authentication Successful",
      shop,
    });
  } catch (error) {
    // Log any errors during authentication
    console.log("Authentication failed:", error);
    return json({ error: "Authentication failed", details: error.message });
  }
};

export default function AppApi() {
  return (
    
      # App Proxy Route - JSON Data
      

This route handles the app proxy requests.

    

  );
}

I have a feeling Im overcomplicating it :anguished_face: my remix terminal gave me the following:

15:31:20 │ remix │ Incoming Query Parameters:
15:31:20 │ remix │ Shop: non-null-value
15:31:20 │ remix │ Signature:
non-null-value
15:31:20 │ remix │ Timestamp: non-null-value
15:31:20 │ remix │ [shopify-app/INFO] Authenticating app proxy request
15:31:20 │ remix │ Authentication successful: {
15:31:20 │ remix │ shop: ‘non-null-value’,
15:31:20 │ remix │ session: Session {
15:31:20 │ remix │ id: ‘non-null-value’,
15:31:20 │ remix │ shop: ‘non-null-value’,
15:31:20 │ remix │ state: ‘’,
15:31:20 │ remix │ isOnline: false,
15:31:20 │ remix │ scope: ‘write_products’,
15:31:20 │ remix │ expires: undefined,
15:31:20 │ remix │ accessToken: ‘non-null-value’,
15:31:20 │ remix │ onlineAccessInfo: undefined
15:31:20 │ remix │ }

edit: i also didnt see a .env file after my initial shopify app init. i just made one manually

oh you know what, I also had issues with the loader function throwing errors when I tried to hit the shop and admin during the await authenticate.public.appProxy(request)! could you maybe delete your current loader and just try this snippet to confirm app proxy is coming through correctly:

export const loader = async ({ request }) => {

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

  return liquid("Wow {{shop.name}} goes here");

};

that worked!

that’s so interesting.. So if I were to add buttons to this proxy page now it can still be in this app.api.jsx correct? My goal is to do simple GET/POST from my external api and have it display on my proxy page - can all that logic be done in one file?

thanks so much for your time, truly you helped me make a breakthrough.

awesome, glad it worked! There definitely must be something bugged with the {admin, shop} then. But yeah technically if you wanted to load data and FE on the one proxy page you can do it there. just make sure to have the return() JSX function with your Polaris components. For loading data, I use graphQL on the loader() function which also had some quirks, but ofc, I think you’re set from there! if you run into anything I may be able to assist, all the best

1 Like