"admin.shopify.com refused to connect" when trying to redirect to confirmation url

Hello,

I am developing a Shopify App (theme extension app), and am running into a usage billing problem.

When I try to redirect to the confirmation url once a usage billing subscription creation request has been made, it just gets blocked by a “admin.shopify.com refused to connect” error.

Here is my code:

// app/routes/_app.jsx (example filename)
import { Link, Outlet, useLoaderData, useRouteError } from "@remix-run/react";
import { redirect } from "@remix-run/node";
import { boundary } from "@shopify/shopify-app-remix/server";
import { AppProvider } from "@shopify/shopify-app-remix/react";
import { NavMenu } from "@shopify/app-bridge-react";
import polarisStyles from "@shopify/polaris/build/esm/styles.css?url";
import { authenticate } from "../shopify.server";

export const links = () => [{ rel: "stylesheet", href: polarisStyles }];

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

  const graphQLResponse = await admin.graphql(`
    query getActiveSubscriptions {
      app {
        installation {
          launchUrl
          activeSubscriptions {
            id
            name
            status
            currentPeriodEnd
          }
        }
      }
    }
  `);

  const { data } = await graphQLResponse.json();
  const { activeSubscriptions, launchUrl } = data.app.installation;

  if (activeSubscriptions.length < 1) {
    const createResponse = await admin.graphql(
      `
        mutation AppSubscriptionCreate(
          $name: String!
          $lineItems: [AppSubscriptionLineItemInput!]!
          $returnUrl: URL!
        ) {
          appSubscriptionCreate(
            name: $name
            returnUrl: $returnUrl
            lineItems: $lineItems
          ) {
            userErrors {
              field
              message
            }
            appSubscription {
              id
              lineItems {
                id
                plan {
                  pricingDetails
                  __typename
                }
              }
            }
            confirmationUrl
          }
        }
      `,
      {
        variables: {
          name: "Super Duper Usage Plan",
          returnUrl: launchUrl,
          lineItems: [
            {
              plan: {
                appUsagePricingDetails: {
                  terms: "$1 for 100 emails",
                  cappedAmount: {
                    amount: 20.0,
                    currencyCode: "USD",
                  },
                },
              },
            },
          ],
        },
      }
    );

    const createResult = await createResponse.json();

    const confirmationUrl =
      createResult.data.appSubscriptionCreate.confirmationUrl;

    return redirect(confirmationUrl);
  }

  return ({ apiKey: process.env.SHOPIFY_API_KEY || "" });
};

export default function App() {
  const { apiKey } = useLoaderData();

  return (
    <AppProvider isEmbeddedApp apiKey={apiKey}>
      <NavMenu>
        <Link to="/app" rel="home">
          Home
        </Link>
        <Link to="/app/dashboard">Dashboard</Link>
        <Link to="/app/configurations">Configurations</Link>
        <Link to="/app/public-dashboard">Public Dashboard</Link>
        <Link to="/app/support">Support</Link>
        <Link to="/app/badges-banners">Badgers and Banners</Link>
      </NavMenu>
      <Outlet />
    </AppProvider>
  );
}

export function ErrorBoundary() {
  return boundary.error(useRouteError());
}

export const headers = (headersArgs) => {
  return boundary.headers(headersArgs);
};

Any assistance with this would be much appreciated. Thank you!

Two things you might wanna try (literally just got this working myself). You need to replace the redirect with the one from shopify and then also set the target.

const { redirect } = await authenticate.admin(request);
...
return redirect(response.data.appSubscriptionCreate.confirmationUrl,{ target: "_parent" })

Worked like a charm, thanks for your help :raising_hands: