Hi, I’m using Netlify to host a Shopify app that is run inside an iframe in the Shopify dashboard. Shopify requires that I set the proper Content Security Policy frame-ancestors directive to avoid clickjacking attacks. The frame-ancestors header should be set dynamically to whatever shop origin has loaded the app. I read the _headers docs on Netlify and did some searching but couldn’t find anything if this is even possible. Others have accomplishes this by using middleware to set the CSP header unfortunately my app is a JavaScript SPA. Any help is greatly appreciated. Thanks!
Hi, @philnetlify1. To confirm, is this something you looking to solve programmatically because there are many shops being used so the subdomain cannot be known before hand?
If so, Edge Handlers would be a solution once they become publicly available. In the meantime, the only solution I see is to use a function to dynamically generate the headers.
Yes, you are correct. Basically I will need to programmatically validate the domain *.myshopify.com and then set the frame-ancestors to whichever shop domain is being used. The subdomain cannot be know before hand. I’ll look into functions. Thanks!
Hi @philnetlify1 Did you solve this? Can you share your functions file on how did you achieve this?
I have created a file in root-app-folder/.netlify/functions/index.js and this function never gets called.
Hey @srameshr , I ended up switching over to Cloudflare Workers Sites. The following gist got me started configuring my web worker script. Some of it is probably applicable to Netlify function too. Hope it helps
Yes, but how do we achieve this to set headers on Netlify functions? Functions wont be run on beforePageRequest right? They are just like API endpoints if you dont want to spin up your own API servers
Hey there folks! Just chiming in here to say we are working on a project that might make this possible in the future. I can’t share a timeline, but stay tuned!
As always, thanks for bringing great collaboration and great ideas to the Forums.
Got it. For anyone else that finds this, here’s the function I wrote that seemed to pass Shopify approval:
// Handler to check the request header for a shopify domain and if it is there, include it in the response headers frame-acnestor list
export default async (request, context) => {
const response = await context.next();
// Get rid of everything before the ? in the URL
const bits = request.url.split("?");
// If shopify domain is present, add it to the response headers frame-ancestor list
if (bits.length >= 2) {
// Get the "shop" param from the query string
const queryString = new URLSearchParams(bits[1]);
const shop = queryString.get("shop");
// If domain ends with "myshopify.com", allow it
if (shop.endsWith("myshopify.com")) {
response.headers.set(
"Content-Security-Policy",
`frame-ancestors https://admin.shopify.com https://${shop}`
);
}
}
return response;
};
@fool The docs say to not use edge functions in production, but don’t go into any more detail on timeline or the risks. Can you enlighten us?
We don’t have a firm timeline for GA. We and many other customers do already use them in production, but since they’re a beta feature, there could be instability or breaking changes to the API until we do release.
We’ll definitely make a lot of noise when they are GA-ready!