Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with host parameter persistence with App Bridge React v4 updates #1332

Open
br34th3r opened this issue Aug 20, 2024 · 3 comments
Open

Comments

@br34th3r
Copy link

We currently use this template to run an application handling multiple stores. In an attempt to upgrade our @shopify/app-bridge-react module to v4 we have encountered a series of changes that have broken the app in multiple places. I've fixed all bar the "host parameter is missing" issue. This occurs when the store auth callback is run, the initial page is loaded correctly, but then upon navigation, the host parameter is no longer persisted across pages, and as such the page fails to load app bridge.

I am using the default functions built in to handle auth and callback (shopify.auth.begin() and shopify.auth.callback()) and it seems to work but it's just the frontend app with React and Vite that seems to be causing trouble. I have attempted to use createApp() from @shopify/app-bridge to rectify the change from useAppBridge() -> ClientApplication to useAppBridge() -> ShopifyGlobal where we now define const shopifyApp = createApp(config) in the index.jsx file but this seems to be re-rendered on every page, so I can't see how I'm supposed to persist the host value if it's passed through once to the frontend as a parameter.

index.jsx
Below are the files of relevance, if someone could point me in the right direction, I'd be very appreciative:

import { createRoot } from "react-dom/client";
import { createApp } from "@shopify/app-bridge";
import { initI18n } from "./utils/i18nUtils";
const config = {
    apiKey: process.env.SHOPIFY_API_KEY,
    host: new URLSearchParams(location.search).get("host") || window.__SHOPIFY_DEV_HOST,
    forceRedirect: true,
};
console.log(config);
const shopifyApp = createApp(config);
import App from "./App";
const container = document.getElementById("app");
const root = createRoot(container);
root.render(<App app={shopifyApp} />);

server.js

// Just the auth flow
app.get(shopify.config.auth.path, shopify.auth.begin());
app.get(
  shopify.config.auth.callbackPath,
  shopify.auth.callback(),
  // flareInit ends with a call to next() and just does some processing on our end (a few GQL queries and DB calls)
  flareInit,
  shopify.redirectToShopifyOrAppRoot()
);

app.post(
  shopify.config.webhooks.path,
  shopify.processWebhooks({ webhookHandlers: WebhookHandlers })
);

ExitIframe.jsx

import { Redirect } from "@shopify/app-bridge/actions";
import { useAppBridge } from "@shopify/app-bridge-react";
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { Banner, Layout, Page, Text } from "@shopify/polaris";

export default function ExitIframe({ app }) {
  const { search } = useLocation();
  const [showWarning, setShowWarning] = useState(false);

  useEffect(() => {
    if (!!app && !!search) {
      const params = new URLSearchParams(search);
      const redirectUri = params.get("redirectUri");
      const url = new URL(decodeURIComponent(redirectUri));

      if (
        [location.hostname, "admin.shopify.com"].includes(url.hostname) ||
        url.hostname.endsWith(".myshopify.com")
      ) {
        const redirect = Redirect.create(app);
        redirect.dispatch(
          Redirect.Action.REMOTE,
          decodeURIComponent(redirectUri)
        );
      } else {
        setShowWarning(true);
      }
    }
  }, [app, search, setShowWarning]);

  return showWarning ? (
    <Page narrowWidth>
      <Layout>
        <Layout.Section>
          <div style={{ marginTop: "100px" }}>
            <Banner title="Redirecting outside of Shopify" status="warning">
              Apps can only use /exitiframe to reach Shopify or the app itself.
            </Banner>
          </div>
        </Layout.Section>
      </Layout>
    </Page>
  ) : <Text>Loading...</Text>
}
@paulomarg
Copy link
Collaborator

Hey, thanks for raising this. Just to make sure I'm fully understanding the problem, this is the request timeline:

  1. OAuth works ok, Shopify calls the callback endpoint
  2. Callback endpoint redirects to the app's root
  3. App root loads ok inside the admin
  4. User navigates away from the page
    1. Using a link in the page?
    2. Using the left sidebar?
  5. App attempts to load the page <= fails because the host param is missing

Could you just confirm this is correct so we can investigate it?

@br34th3r
Copy link
Author

Hi @paulomarg, yes that's correct, the navigation can be either be a link on the page or in the sidebar, the same result occurs where the host param is missing in both cases.

@noskap
Copy link

noskap commented Oct 29, 2024

Experiencing the same issues on v3 app bridge as well as v4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants