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 (-:
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 (-:
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 (
Im passing authAxios down to Component and use axios in that way, when i need authenticated requests.
```javascript
authAxios.get('/api/products')
.then(result => console.log(result))
.catch(error => console.log(error))
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 (
);
}
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.
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 ?