// web/backend/routes/index.js
import verifyRequest from '../middleware/verify-request.js'
// all root routes *must* be prefixed with `api` since that is the prefix shopify uses for the callback uri during auth.
// If you do not do this your routes will fail
router.use('/api/authCheck', verifyRequest(), (req, res) => {res.status(200).send('ok')})// This route is used to determine if the client needs to redirect to auth.
// AppFrame.js
import { useServerClient } from '../../hooks/index';
import { useEffect } from 'react';
export default function AppFrame() {
const serverClient = useServerClient()
useEffect(() => {
serverClient.get('/api/authCheck', {baseURL: ''}) // This api call checks if the user is authenticated on app load
}, [])
// useServerClient.js
import axios from 'axios'
import { useAppBridge } from "@shopify/app-bridge-react";
import { getSessionToken } from "@shopify/app-bridge-utils";
import { Redirect } from "@shopify/app-bridge/actions";
export function useServerClient(axiosOptions = {}){
const app = useAppBridge();
function checkHeadersForReauthorization(headers, app) {
if (headers.get("X-Shopify-API-Request-Failure-Reauthorize") === "1") {
let authUrlHeader = headers.get("X-Shopify-API-Request-Failure-Reauthorize-Url")
if(authUrlHeader.includes('?shop=null')){
const shop = window.localStorage.getItem('OSB_SHOP')
authUrlHeader = `/api/auth?shop=${encodeURIComponent(shop)}`
}else{
const shop = authUrlHeader.split('?shop=')[1]
window.localStorage.setItem('OSB_SHOP', shop)
}
const redirect = Redirect.create(app);
redirect.dispatch(
Redirect.Action.REMOTE,
authUrlHeader.startsWith("/")
? `https://${window.location.host}${authUrlHeader}`
: authUrlHeader
);
}
}
const defaultOptions = {
baseURL: "/api/v1",
timeout: 100000,
};
const options = {
...defaultOptions,
...axiosOptions
}
const serverClient = axios.create(options);
serverClient.interceptors.request.use(function (config) {
return getSessionToken(app) // requires a Shopify App Bridge instance
.then((token) => {
// Append your request headers with an authenticated token
config.headers["Authorization"] = `Bearer ${token}`;
return config;
});
});
serverClient.interceptors.response.use(function (response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
}, function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
if (error.response.status === 403) {
checkHeadersForReauthorization(error.response.headers, app)
}
return Promise.reject(error);
});
return serverClient
}