Michael-Gibbons / OSB

An Opinionated Full Stack Shopify App Boiler
MIT License
19 stars 2 forks source link

Fix session bug once db is migrated in development mode #114

Open Michael-Gibbons opened 1 year ago

Michael-Gibbons commented 1 year ago
// 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
}