OAuth flow for React App with Node Backend (split) | Admin embedded App

AI-generated summary

OAuth for an embedded Shopify admin app is failing in a split architecture: a React frontend using App Bridge 2.0 and a separate Node backend handling authentication. The main symptom is the recurring error: Cannot complete OAuth process. Could not find an OAuth cookie for shop url.

Key points raised:

  • The frontend receives Shopify query parameters (hmac, shop, timestamp, etc.) and redirects to a backend /auth endpoint for validation.
  • App installation completes, but the app later fails when App Bridge or a post-auth redirect is used.
  • A second example shows the same error after the subscription/approval step in production (Heroku), even though it works locally.

Technical context:

  • The backend uses Shopify auth middleware and sets cookies such as shopOrigin with secure: true and sameSite: "none".
  • The failure appears tied to OAuth state/cookie persistence across redirects, especially with separate frontend/backend domains or deployment differences.

Open questions remain:

  • Whether the app URL should point to frontend or backend.
  • Whether redirects versus direct requests are expected in this OAuth flow.
  • No clear resolution is provided in the discussion.

Hi,

I currently have the following setup to try to authenticate an Admin Embedded Public App.

  • Frontend React app with latest version of App Bridge 2.0
  • Backend Node app using shopify-api-node

I’m struggling with the whole OAuth flow and trying different options since the documentation is not clear enough on how it should work.

What I have right now is:

App url points to a url in my frontend react app (frontend-domain/install), that page grabs all the query params (hmac, shop, timestamp, etc.) and redirects to a backend-domain/auth (which I’ve added to the list of callback urls) where the logic to validate the request happens and afterwards tries to redirect to frontend-domain/home. I do receive the install prompt and the app gets installed but then when I try to use app bridge in the frontend (everything is wrapped in a Provider component as the doc suggests) and then I get a Cannot complete OAuth process. Could not find an OAuth cookie for shop url.

I don’t know what’s wrong. I’ve found some post of people being able to have a frontend and backend separate domains and still make this work but the entire Shopify documentation and examples circle in a single app that does everything together.

Is the app setting for app url correct? Should I do a redirect or a GET request?

Any help would be greatly appreciated since I’ve been stuck for weeks on this trying different approach.

(I initially posted this in the wrong subsection but I’m not sure how to delete the other thread)

I’m looking to add to this, When I install the app via a heroku deployment, I get to the permissions step on install, however when the redirect occurs for the subscription part of the step, I get an internal server error that reads the following:

Cannot complete OAuth process. Could not find an OAuth cookie for shop url

server.use(
    createShopifyAuth({
      async afterAuth(ctx) {
        ctx.cookies.set("shopOrigin", shop, {
          httpOnly: false,
          secure: true,
          sameSite: "none",
        });

        // Access token and shop available in ctx.state.shopify
        const { shop, scope, accessToken } = ctx.state.shopify;
        ACTIVE_SHOPIFY_SHOPS[shop] = scope;

        const registration = await Shopify.Webhooks.Registry.register({
          shop,
          accessToken,
          path: "/webhooks",
          topic: "APP_UNINSTALLED",
          apiVersion: ApiVersion.October20,
          webhookHandler: (_topic, shop, _body) => {
            console.log("App uninstalled");
            delete ACTIVE_SHOPIFY_SHOPS[shop];
          },
        });

        if (registration.success) {
          console.log("Successfully registered webhook!");
        } else {
          console.log("Failed to register webhook", registration.result);
        }
        // console.log(ctx);
        // Redirect to app with shop parameter upon auth
        const returnUrl = `https://${Shopify.Context.HOST_NAME}?shop=${shop}`;
        const subscriptionUrl = await getSubscriptionUrl(
          accessToken,
          shop,
          returnUrl
        );
        ctx.redirect(subscriptionUrl);
      },
    })
  );

This step works fine, however when I click Update unlisted sales channel, I get the Internal server error page, and checking the heroku logs shows the error as Cannot complete OAuth process. Could not find an OAuth cookie for shop url error.

This all works fine in local host, am I simply missing a step at deployment?