I have 2 apps in my monorepo. App A is assigned domainA.com and App B is assigned domainB.com
Plan is to open domainB.com in an iframe in domainA.com. All this works locally when the 2 domains are on localhost:3000 and localhost:3001, but once deployed, domainB.com is blocked inside the iframe with the following error on Chrome:
Because your site has the Cross-Origin Embedder Policy (COEP) enabled, each resource must specify a suitable Cross-Origin Resource Policy (CORP). This behavior prevents a document from loading cross-origin resources which don’t explicitly grant permission to be loaded.To solve this, add the following to the resource’ response header:Cross-Origin-Resource-Policy: same-site if the resource and your site are served from the same site.Cross-Origin-Resource-Policy: cross-origin if the resource is served from another location than your website. ⚠️If you set this header, any website can embed this resource.Alternatively, the document can use the variant: Cross-Origin-Embedder-Policy: credentialless instead of require-corp. It allows loading the resource, despite the missing CORP header, at the cost of requesting it without credentials like Cookies.When I inspect the request to domainB.com when loaded inside iframe, there are no headers in the response. But when i open domainB.com outside an iframe, the response has all the headers required.
next.config.mjs for domainA:
/** @type {import('next').NextConfig} */const nextConfig = { // reactStrictMode: false, // Uncomment to see if duplicate requests are due to React Strict Mode async headers() { return [ { source: "/(.*)", headers: securityHeaders, }, ]; }, async rewrites() { return [ { source: "/home", destination: "/", }, ]; }, experimental: { swcPlugins: [ [ "@preact-signals/safe-react/swc", { // you should use `auto` mode to track only components which uses `.value` access. // Can be useful to avoid tracking of server side components mode: "auto", } /* plugin options here */, ], ],next.config.mjs for domainB:
/** @type {import('next').NextConfig} */const nextConfig = { // reactStrictMode: false, // Uncomment to see if duplicate requests are due to React Strict Mode pageExtensions: ["js", "jsx", "ts", "tsx", "md", "mdx"], async headers() { return [ { source: "/(.*)", headers: securityHeaders, }, ]; },};const ContentSecurityPolicy = ` default-src 'self' vercel.live; script-src blob: 'self' 'unsafe-eval' 'unsafe-inline' cdn.vercel-insights.com vercel.live va.vercel-scripts.com pyscript.net https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/ https://cdn.jsdelivr.net/pyodide/ https://cdn.jsdelivr.net/npm/@pyscript/ https://cdn.jsdelivr.net/npm/@micropython/; worker-src 'self' blob: data:; style-src * 'self' 'unsafe-inline'; img-src * blob: data:; media-src 'none'; connect-src * blob:; font-src * 'self' data:; frame-src 'self' vercel.live; frame-ancestors 'self' https://pykernel.com https://www.pykernel.com http://localhost:3000;`;const securityHeaders = [ { key: "Content-Security-Policy",why does domainB get the headers in the response when opened by itself and why are these headers missing when opened inside an iframe?
Opened in iframe:

Opened standalone:
