Configuring Content Security Policy
Allow the EmbedAuth iframe under a strict CSP — the exact frame-src directive, the email-redirect origin most people miss, and per-framework header examples.
If your site sends a Content-Security-Policy header — and in production it should — the browser will refuse to load any iframe whose origin is not explicitly allowed. This is the single most common reason an embed that "worked on localhost" shows a blank frame in production.
The directive you need
Allow the EmbedAuth origin in your frame-src directive:
Content-Security-Policy: frame-src https://embedauth.com;
frame-src governs what may be loaded into <iframe> and <frame> elements. If you do not set frame-src, browsers fall back to default-src — so if you have a restrictive default-src, you must add frame-src explicitly.
The origin people forget
If your account serves the embed asset from a CDN origin that differs from the app origin, both must appear in frame-src. Password-reset and magic-link emails open at the app origin first and then redirect to the CDN, so a redirect chain crosses both origins:
Content-Security-Policy: frame-src https://embedauth.com https://cdn.embedauth.com;
Check your dashboard for the exact origins your app uses. Omitting the second one produces an embed that works for password sign-in but breaks the moment a user clicks a magic link.
Per-platform examples
Nginx
add_header Content-Security-Policy "frame-src https://embedauth.com;" always;
Express / Node.js
res.setHeader('Content-Security-Policy', "frame-src https://embedauth.com;");
Next.js (next.config.js)
const csp = "frame-src https://embedauth.com;";
module.exports = {
async headers() {
return [{
source: '/:path*',
headers: [{ key: 'Content-Security-Policy', value: csp }],
}];
},
};
HTML meta tag (use only if you cannot set a header)
<meta http-equiv="Content-Security-Policy"
content="frame-src https://embedauth.com;">
Merging with an existing policy
You almost certainly already have a CSP with several directives. Add frame-src alongside them rather than replacing the whole header:
Content-Security-Policy:
default-src 'self';
script-src 'self';
frame-src https://embedauth.com;
Directives are separated by semicolons. Each directive is independent — adding frame-src does not loosen script-src or default-src.
Verifying it works
Open your browser's developer console on the page hosting the embed. A CSP violation logs a message like "Refused to frame 'https://embedauth.com' because it violates the following Content Security Policy directive: frame-src …". If you see that, the origin in the message is the one you need to add. No message and a visible form means your policy is correct.
Next steps
- Still blank after fixing CSP? Work through Troubleshooting.
- Wiring the frame into your app: React, Next.js, Vue.