Getting session token in axios intercept

Malthe
Tourist
7 0 3

Hey everyone!

I'm building an embedded app with Next.js as my frontend, and Next.js api routes as my serverless backend. 

I have set my backend up to accept and verify JWT session tokens, which seems to work fine. However my problem lies in my way of sending authenticated requests from my frontend to my backend.

I have set up the app  bridge and was using getSessionToken(app) function to  get the current JWT, but since that is only valid for one minute I have to request a the newest one on every request.

Since I'm using axios for requests to my backend, I followed this tutorial: https://shopify.dev/tutorials/use-session-tokens-with-axios. But after implementing that, I'm getting the following errors on my frontend: TypeError: Cannot read property 'subscribe' of undefined.

This is the exact code for my axios intercept:

import axios from 'axios';
import { getSessionToken } from "@shopify/app-bridge-utils";


const instance = axios.create({
    baseURL: process.env.DEV_TUNNEL_URL,
    headers: {
        post: { // Can be common or any other method
            'Content-Type': 'application/json'
        },
        patch: {
            'Content-Type': 'application/json'
        },
        delete: {
            'Content-Type': 'application/json'
        },
    }
});

// Intercept all requests on this axios instance
instance.interceptors.request.use((config) => {
    console.log(window.app)
    return getSessionToken(window.app) // requires an App Bridge instance
        .then((token) => {
            // Append your request headers with an authenticated token
            config.headers["Authorization"] = `Bearer ${token}`;
            return config;
        });
});

 

I also noticed that window.app is undefined. How can I get the correct app reference in a react app using axios intercept?

 

I hope you can help me shin some light on this (-:

Thanks very much in advance!

Replies 15 (15)
Mircea_Piturca
Shopify Partner
1540 43 332

Hey there,

Yeah, I've been playing with this all day today. Got the same error, not defined.

I've ended up creating an app by passing the API_KEY and shopOrigin on _app.js

  const app = createApp({
    apiKey: API_KEY,
    shopOrigin: shopOrigin
  });

 

I have both of those vars defined in _app.js. Looks like a hack but it's the only way I got it to work.

The docs are a bit confusing to me. 

Finally—Add variant descriptions to your products
JoshHighland
Shopify Expert
88 2 45
import axios from 'axios';
import { useAppBridge } from '@shopify/app-bridge-react';
import { getSessionToken } from '@shopify/app-bridge-utils';

const app = useAppBridge();

 

You can use useAppBridge to gain access to app also.

Malthe
Tourist
7 0 3

Thank you for your answer! Will this also work outside of a react component?

 

HerculesApps
Shopify Partner
10 1 13

Hey @Malthe, did u get this work now?

Malthe
Tourist
7 0 3

Hey. No not exactly I'm afraid. 

I ended up using the authenticatedFetch function that app bridge provides. But I would prefer to use axios to be honest. Let me know if you figure it out (-:

HerculesApps
Shopify Partner
10 1 13

I could get it to work in that way:

File: _app.js

 

function MyProvider(props) {
  const app = useAppBridge();

  // Create axios instance for authenticated request
  const authAxios = axios.create();
  // intercept all requests on this axios instance
  authAxios.interceptors.request.use(function (config) {
    return getSessionToken(app)
      .then((token) => {
        // append your request headers with an authenticated token
        config.headers["Authorization"] = `Bearer ${token}`;
        return config;
      });
  });

  const Component = props.Component;

  return (
      <Component {...props}  authAxios={authAxios} />
  );
}

 

Im passing authAxios down to Component  and use axios in that way, when i need authenticated requests. 

 

  authAxios.get('/api/products')
      .then(result => console.log(result))
      .catch(error => console.log(error))

 

Hope it helps.

 

Malthe
Tourist
7 0 3

Awesome! I will give that a try, thank you.

Bradyango
New Member
1 0 0

Evening Sir!

Any luck on this? 

We are facing a very similar issue. 

scole954387
Excursionist
19 1 10

I'm very new to react/node.  I tried to use what you provided with the shopify CLI boilerplate app and it doesn't seem to work.  Can you tell me what I've done wrong?  Thanks!

 

function MyProvider(props) {
  const app = useAppBridge();

  // Create axios instance for authenticated request
  const authAxios = axios.create();
  // intercept all requests on this axios instance
  authAxios.interceptors.request.use(function (config) {
    return getSessionToken(app)
      .then((token) => {
        // append your request headers with an authenticated token
        config.headers["Authorization"] = `Bearer ${token}`;
        return config;
      });
  });


  const client = new ApolloClient({
    fetch: authenticatedFetch(app),
    fetchOptions: {
      credentials: "include",
    },
  });

  const Component = props.Component;

  return (
    <ApolloProvider client={client}>
      <Component {...props} authAxios={authAxios} />
    </ApolloProvider>
  );
}
dgtlmonk
Shopify Partner
18 1 4

i'm getting 'jwt expired' error

nkm22
New Member
1 0 0

we're having a similar issues using axios interceptor. Any update. Thanks.

Avi_Ben_Zaken
Excursionist
14 0 6

Hey, thanks for this explanation.

can you please show a fully page code that use the authAxios?

iozyigit
Shopify Partner
23 1 2

Seems like hook can be used in functional component.

the question is to use in app instance in the interceptor for the Axios instance. there is no component here and you can not use probably

const app = useAppBridge()

https://www.linkedin.com/in/ismailozyigit/
iozyigit
Shopify Partner
23 1 2

Here is how solve it.  Since I can use hook here I did use "app = useAppBridge()" and add JWT token to header and pass header to Axios instance. useFetchDataApiShopify is kind of single point to make api call. I was trying to use interceptor to add token to header but I was not able to use useAppBridge in the interceptor.

 

 

 

mport React from 'react';
import AxiosShopify from '../../AxiosShopify';
import { useAppBridge } from '@shopify/app-bridge-react';
import { getSessionToken } from '@shopify/app-bridge-utils';

const config = {
	headers: {
		'Content-Type': 'application/json',
		Accept: 'application/json',
	},
};
/*
this is custom hook that fetch data from my backend
*/
export const useFetchDataApiShopify = (url) => {
	const app = useAppBridge();
	const [responseData, setResponseData] = React.useState(undefined);
	const [isError, setIsError] = React.useState(undefined);
	const [isLoading, setIsLoading] = React.useState(undefined);

	React.useEffect(() => {
		const fetchData = async (url) => {
			setIsLoading(true);
			try {
				const token = await getSessionToken(app);
				config.headers['Authorization'] = `Bearer ${token}`;
				const result = await AxiosShopify.get(url, config);
				setResponseData(await result.data);
				console.log('set response fetch11', result);
				setIsLoading(false);
			} catch (error) {
				//	console.log('set response fetch error', error);
				setIsError(error);
			}
		};

		fetchData(url);
	}, [url]);
	return [responseData, isError, isLoading];
};

//*****Interceptor file became like this *******

mport React from 'react';
import axios from 'axios';
import { getSessionToken } from '@shopify/app-bridge-utils';

const AxiosShopify = axios.create();
AxiosShopify.interceptors.request.use(function (config) {
	// return getSessionToken(window.app) // requires a Shopify App Bridge instance
	// 	.then((token) => {
	// 		// Append your request headers with an authenticated token
	// 		config.headers['Authorization'] = `Bearer ${token}`;
	// 		return config;
	// 	});
	return config;
});
// Export your Axios instance to use within your app
export default AxiosShopify;

 

 

 

 

https://www.linkedin.com/in/ismailozyigit/
Tomasz88
New Member
1 0 0

Hi HerculesApps, 

 

I've applied your solution, but I'm getting a 302 status and HTML as a response when I make a API call request front side. Do you have any idea of what is going on ?