Embedded App Oauth Not Working - There’s no page at this address

Embedded App Oauth Not Working - There’s no page at this address

BlackMagic
Shopify Partner
5 0 1

FWIW: My backend is Java, so I'm not using the Ruby or Node quick start libraries there.  This is a little long, sorry!

 

I have my app working as standalone: OAuth install and authorization, standalone app page working, API calls to Shopify working, etc...  

 

However, now I'm trying to get it to work as an embedded app instead, and running into issues.  If the app was installed to my test store as standalone, and then I switch over to embedded mode, it works great.  However if the app has not been installed, then things are failing to work the way I'd expect.

 

I'm new to this (Shopify app development, and React) so I may be making an obvious mistake somewhere here. 

 

In standalone mode my main application page is a "protected page" via OAuth, so it automatically triggers the OAuth flow if it's not already authorized.

 

In embedded mode, as I understand it, the main page has to be unprotected, load in AppBridge, check to see if the app has been installed for this store or not, if yes, then display the embedded admin page content, if no, then redirect to the OAuth install flow.

 

 

if (data.AuthCheckResponse.authenticated) {
                    console.log("authCheck success");
                } else {
                    console.log("authCheck failed");
                    const apiKey = config.apiKey;
                    const redirectUri = "https://myngrokhostnamehere.ngrok.io/oauth2/authorization/shopify";
                    const permissionUrl = `https://${host}/admin/oauth/authorize?client_id=${apiKey}&scope=read_products,read_content&redirect_uri=${redirectUri}`;

                    console.log("Redirecting to: " + permissionUrl);
                    // window.location.href = data.AuthCheckResponse.authRedirectURL;
                    // If the current window is the 'parent', change the URL by setting location.href
                    if (window.top == window.self) {
                        window.location.assign(permissionUrl);

                        // If the current window is the 'child', change the parent's URL with Shopify App Bridge's Redirect action
                    } else {
                        Redirect.create(app).dispatch(Redirect.Action.REMOTE, permissionUrl);
                    }
                }

 

 

 What is happening is when I try to install the app, I get taken to my page (outside of the admin).  At this point I would expect the code above to run, and perform a redirect if needed.  However, what actually happens is I see this error in the browser's console:

 

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('<URL>') does not match the recipient window's origin ('<URL>').

 

 

Then the browser is redirected (by AppBridge?) to my test store's admin, with a URL like this:  https://my-test-store.myshopify.com/admin/apps/$longbase64value/dash-embedded?hmac=fabbe9da79caad695...

 

Which displays an embedded error page saying "There's no page at this address" - screenshot: https://share.getcloudapp.com/nOuRNv0A

 

After the redirect to the Shopify admin happens, there are no requests to my backend made.   I don't know where the redirect to the admin is coming from, nor do I know why it isn't trying to load the embedded page from my backend.

 

Any ideas?  I may well be doing something very wrong here, as the documentation around embedded app behavior assumes you're using their SDKs and a great deal of "magic" happens there.  

 

Thanks!

Replies 3 (3)

Colin88
Shopify Partner
5 0 1

I’m not sure if this is the issue, but I don’t believe you should be manually creating the auth url. Try the below method -

const authRoute = await Shopify.Auth.beginAuth(req, res, shop, "/auth/callback", isOnline);

 
It also looks like you constructed the url with the host var, it should be the shop domain. The above code should fix that

BlackMagic
Shopify Partner
5 0 1

Thanks for the reply.  I think that code only applies if you're using the Shopify SDK Node backend, and doesn't apply/work from the AppBridge front end, which is where I'm having the issue.

 

The host var is what is used in the example here: https://shopify.dev/apps/tools/app-bridge/getting-started#authorize-with-oauth

 

Which is where I copied the code from.  

 

I think what is happening is that AppBridge is detecting that we aren't embedded in the Shopify Admin and is trying to redirect back into the Admin.  However there's two issues with that I think.  One being that the initial OAuth install has to happen outside of the Admin.  The other being that https://my-test-store.myshopify.com/admin/apps/my-api-key/dash-embedded isn't proxying back to my app's back end at all, and is just 404ing inside the Shopify Admin.  Maybe because it hasn't completed the install process?  But now we're at a catch-22. 

 

The browser console flow looks like this: https://share.getcloudapp.com/d5u9gy9w

 

Right after it says "MyApp called" seems to be where it blows up.  Maybe the getSessionToken call is what triggers the redirect to re-embed the app?  No idea.  

 

 

function MyApp() {
console.log('MyApp called');
var token = getSessionToken(app);
token.then(value => {
console.log("token: " + value);
window.sessionToken = value;
authCheck();
loadProductList();
});
keepRetrievingToken(app);

return (
<Provider config={config}>
<AppProvider i18n={enTranslations}>
<TitleBar title="My page title" />
<h2>This is a test app</h2>
</AppProvider>
</Provider>
);
}

 

 
Any suggestions would be greatly appreciated!  Thanks!
BlackMagic
Shopify Partner
5 0 1

I have solved this.  You can't call getSessionToken if the app isn't already installed.  You have to perform the authCheck (which checks to see if the App has been installed to the current Store or not) FIRST.  And then if not, trigger the OAuth redirect, and if so then proceed with getSessionToken, etc...

 

The OAuth install flow redirect URL looks like this:  

 

const permissionUrl = `https://${shopName}/admin/oauth/authorize?client_id=${apiKey}&scope=${scopes}&redirect_uri=${redirectUri}`;

 

All is working well now.  I will make a blog post going into more details so hopefully the next person in my situation can find an easy answer:)