Missing Authorization Header on App Proxy Request from Theme App Extension

Laurenkg
Shopify Partner
2 0 0

Hi all, I'm new to the whole app proxy thing. I'm trying to pull data from my database from my theme app extension. I have the app proxy set up as follows:

 

subpath prefix: apps,

subpath: custom-orders,

proxy URL: https://clouflarequicktunnelurl.trycloudflare.com/api (whatever quick tunnel I'm currently running to test stuff + "/api"

 

On my backend, I have this endpoint the returns a list of json data for survey responses:

 

 

app.get("/api/surveys", async (req, res) => {
    try {
      const response = await db.listSurveys(
        await getShopUrlFromSession(req, res)
      );
      
      res.status(200).send(response);
    } catch (error) {
      console.error(error);
      res.status(500).send(error.message);
    }
  });

 

 

This works from the merchant side of things.

From my theme app extension, I have this in a javascript file extensions/custom-orders/assets/app-block.js

 

 

async function getAllData(){
    try{
        await fetch('/apps/custom-orders/surveys', 
        {method: "GET", 
         headers: {"Content-Type": "application/json"},});
    }catch(err){
        console.error(err);
    }
}

 

 

 and I have a button in my app-block.liquid that calls this function.

I know I'm missing a step, because I am getting this error message

Screenshot 2023-09-20 at 5.55.18 PM.png

I've tried looking at the app proxy documentation, but I can't seem to figure out what else I need to do here. I tried importing authenticatedFetch, but I can't because app-block.js is part of the extension and therefore not a module. Do I need to include something else in the headers? Do I need to handle my own authentication and if so, how do I do that? Help!

Replies 2 (2)

Liam
Shopify Staff
2731 301 778

It's possible that you're facing a Cross-Origin Resource Sharing (CORS) issue. If so you'll need to add CORS headers to your server's responses. Here's a simple example of how to do it:

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

This will allow any client to access your server's resources, which might not be what you want for a production app. You should replace the '*' in 'Access-Control-Allow-Origin' with the specific origins that should be allowed to access your server.

 

Also, note that fetch requests are resolved as soon as headers are received, before the entire body is downloaded. To access the body of the response, you need to use the .json() or .text() methods of the Response object, which return a promise that resolves with the body. Here's how you can modify your fetch request:

async function getAllData(){
    try{
        const response = await fetch('/apps/custom-orders/surveys', 
        {method: "GET", 
         headers: {"Content-Type": "application/json"}});
        const data = await response.json();
        console.log(data);
    }catch(err){
        console.error(err);
    }
}

Please try these suggestions and see if they resolve your issue!

Liam | Developer Advocate @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

Laurenkg
Shopify Partner
2 0 0

Hi Liam, I have a couple questions. First, I added the CORS headers to my index file and I changed my JS code as you suggested. Now, when I try to call getAllData, the network on my browser inspector is showing this as the request URL

Screenshot 2023-09-22 at 2.52.45 PM.png

so it seems like the proxy is not forwarding my requests. What am I doing wrong?

 

Secondly, I looked back in my code (which is modeled from the build an app tutorial code) and I have this line in my index.js, which I imagine is what was causing the problem.

app.use("/api/*", shopify.validateAuthenticatedSession());

However, this doesn't seem like something I'd want to get rid of for security reasons. Should I just replace it with the CORS headers you gave me, or should I leave it in and add the CORS headers?