Solved

App Bridge functions app.getState() and getSessionToken(app) do not resolve

shophelp20
Shopify Partner
11 0 4

We're running into an issue where app.getState() and getSessionToken(app) do not resolve - no results or errors are returned. authenticatedFetch has the same issue but we believe it is due to getSessionToken(app). We can can confirm that the app bridge is loaded and app exists.

Here is the code:

import React, { useContext } from 'react';
import ReactDOM from 'react-dom';
import { createBrowserHistory } from 'history';
import { Router, Route, Switch } from 'react-router-dom';
import { Context, Provider } from '@shopify/app-bridge-react';
import { authenticatedFetch, getSessionToken } from '@shopify/app-bridge-utils';
import COMPONENT from 'app/component.jsx';


let component = COMPONENT;
let apiKey = 'XXXXXXXXXXXX';
let shop = 'YYYYYYYYYYY';

const MyApp = () => {
  const app = useContext(Context);
  if (app) {
    console.log(app)
    
    app.getState()
    .then((state) => console.log('state'))
    .catch((err) => console.log(err));

    getSessionToken(app)
    .then((result) => console.log(result))
    .catch((err) => console.log(err));

    authenticatedFetch(app)('https://www.espn.com/').then(response => console.log(response)).catch((err) => console.log(err))
  }

  return (
    <Router history={createBrowserHistory()}>
      <Switch>
        <Route path='/' component={component} />
      </Switch>
    </Router>
  );
};

ReactDOM.render(
  <Provider config={{ apiKey: apiKey, shopOrigin: shop }}>
    <MyApp />
  </Provider>
, document.getElementById('root'));

The app variable looks like this:

app.png

What are we doing wrong? We just want to grab the session token to replace the cookies for authenticated AJAX calls.

Accepted Solution (1)
iain-campbell
Shopify Staff (Retired)
54 9 23

This is an accepted solution.

Is there a way to allow messages from multiple subdomains?

Unfortunately not; the entire URL origin must match.

To learn more visit the Shopify Help Center or the Community Blog.

View solution in original post

Replies 11 (11)

Michael_Ragalie
Shopify Staff
38 2 12

This might be obvious, but just to be sure: you're trying to use App Bridge within the Shopify Admin, right? As in your app has been loaded as an embedded app in Shopify?

The most common reason why `app.getState()` wouldn't resolve is that our JS or the browser is blocking messages on the `postMessage` channel we use to communicate. This can happen if the app isn't running within the Shopify Admin, or if the shop you instantiated App Bridge with is wrong. I _think_ we might also enforce that the origin of the page that's running the app needs to match the origin of the app's application URL, but I'm not 100% sure on that.

Anyway, I'd check those things first.

To learn more visit the Shopify Help Center or the Community Blog.

shophelp20
Shopify Partner
11 0 4

@Michael_RagalieYes, the app has been loaded as an embedded app in Shopify. We see the postMessage channel errors only when testing locally, but not in production. Presumably this is because the app is not loaded within the Shopify Admin in development. Ah, so the app is on a different subdomain than the application URL (abc.xxxxx.com vs def.xxxxx.com). Does that matter?

Michael_Ragalie
Shopify Staff
38 2 12

You'll need to load the app in the Shopify Admin in development too in order to use App Bridge. You can use ngrok to make a public URL for your app, and then create a separate "draft" Shopify app to test against your local (development) app. Some instructions here: https://www.shopify.ca/partners/blog/shopify-admin-authenticate-app

Once you have your local app setup, you can install that app onto one of your test stores from the Partners Dashboard. More here: https://shopify.dev/concepts/app-store/getting-your-app-approved/testing-your-app-before-submitting#...

To learn more visit the Shopify Help Center or the Community Blog.

shophelp20
Shopify Partner
11 0 4

Yup, I understand that is necessary for the development app.

However, I can confirm that the app is loaded within the Shopify Admin and the App Bridge is loaded in production (I can see the app instance with const app = useContext(Context);). Is there another reason why app.getState()and getSessionToken(app) do not resolve? When I set app = null, these two functions resolve to an error, but nothing is resolved when the actual app is used.

iain-campbell
Shopify Staff (Retired)
54 9 23

Are you loading your app from a different domain than the one you supplied in Partners Dashboard as your app's URL (under 'App Setup')? App Bridge will only accept messages from the domain specified in Partners Dashboard.

To learn more visit the Shopify Help Center or the Community Blog.

shophelp20
Shopify Partner
11 0 4

Hi @iain-campbell,

Yes, the app is hosted on a CDN with a different subdomain (def.xxxx.com) than the one specified on the app URL field (abc.xxxx.com). Is there a way to allow messages from multiple subdomains?

iain-campbell
Shopify Staff (Retired)
54 9 23

This is an accepted solution.

Is there a way to allow messages from multiple subdomains?

Unfortunately not; the entire URL origin must match.

To learn more visit the Shopify Help Center or the Community Blog.

AppUser17
New Member
6 0 0

@iain-campbell  any way to determine if the app is loaded inside the shopify admin and if the app bridge function is going to work ?

The getState and getSessionToken both methods return the promise object but if the app is not loaded inside the shopify admin then it does not hit resolve or reject method. 

I am trying to build the pages that can be served both ways so I need to determine if the app is not loaded inside the shopify admin then load a different layout. 

Please let me know how can I achieve that ?

Thanks

 

Louise_Elmose_H
Shopify Partner
78 2 21

Hi,

I have the same issue as described in the initial post, i.e. the getState and getSessionToken promises do not resolve to a result or an error.

Could you please clarify what the requirements are in order for the promise to resolve?
When reading the posts in this thread, the requirements seems to be:

  1. The app needs to be running as an embedded app. 
  2. The app URL as specified in the app configuration under "App URL" MUST match the URL where the app is running

My app fulfills both of the above requirements, I have a ngrok URL under "App URL" which points to my local environment on http://localhost:3000.

My code is:

import { useEffect, useState, useContext  } from 'react'
import { useAppBridge, Context } from '@shopify/app-bridge-react'
import { getSessionToken  } from '@shopify/app-bridge-utils'

export default function SomeComponent(props) {
  const app = useAppBridge()
  console.log('Hi!', app)
  const app2 = useContext(Context)
  console.log('Hi! 2', app2)

  app.getState()
    .then((state) => console.log('state'))
    .catch((err) => console.log('state error ' + err));

    getSessionToken(app)
    .then((result) => console.log('token ' + result))
    .catch((err) => console.log('token err' + err));
  
  return <h1>Hello!</h1>
}

Please note that the allowed redirect URLs I have points to my app backend URL instead of the "App URL"/frontend URL .

Any input on why the getState() or getSessionToken does not resolve?

Thanks

-Louise

lucasgomide
Visitor
1 0 0

I'm getting the same error, in my case: The react app is being loaded inside an Iframe. Until now I was not able to make my app works this way. 

Anyway, still not clear why the promise is not resolved or reject 

Kris_Doyle
Shopify Partner
140 1 41

I'm having the exact same issue described here, but it's intermittent. If I run two browsers with the same app locally, once in a while, Axios will hang since getSessionToken never resolves to anything, so the whole thing just hangs with no message. This is worst case because there's no way to know that something went wrong without wrapping the whole thing in some kind of weird hacky timer thing (which I'd like to avoid).

 

Mainly just wanted to mention that I'm also running into this problem as I'm converting from cookies to session tokens. Oddly enough, if I do a hard refresh, it starts working again, but if I only refresh the app frame, it doesn't.

 

Also, the app does meet the criteria of the origin URL matching and being inside the app frame.

 

Help 🙂