Cloudflare Access · demo
Embedding an Access app in an iframe
A self-hosted app behind Cloudflare Access will refuse to load inside a cross-site iframe unless a specific set of settings line up. This page embeds one such app and walks through exactly what each setting does — and what breaks when it is missing.
—
allow_iframe lets the
login landing page render in the frame, but the interactive
one-time-PIN verification step still redirects through
a cloudflareaccess.com page that framebusts — so
completing OTP inside the frame fails with "refused to
connect." Reliable paths for the no-session case:
Log in (new tab) to authenticate top-level, then
Reload frame (Access preemptively sets the app
cookie, so the frame then loads with no login); or, for production,
move identity into the app (Salesforce Canvas signed request / service
token). Third-party-cookie blocking (Safari ITP, strict Chrome) is the
other reason in-frame login won't complete.
How this is configured
This demo points at
- Embedded app
—- Team domain
—- Parent origin
—
Enable allow_iframe (Access settings API)
curl -X PATCH \
"https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id}/settings" \
-H "Authorization: Bearer {API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{ "allow_iframe": true }'
allow_iframe and skip_interstitial are the
two body parameters. Returns the updated settings on success.
Cookie setting (dashboard)
Zero Trust → Access controls → Applications → your app → Advanced settings → Cookie settings → SameSite Attribute = None.
The per-app CF_Authorization cookie defaults to
None (admin choice). Setting it to Lax or
Strict is what breaks the cross-site embed.
CORS setting (dashboard)
Same app → Advanced settings → CORS settings. Set
Access-Control-Allow-Origin to this parent origin and
enable Access-Control-Allow-Credentials, or bypass
OPTIONS to origin if your app handles CORS itself.
Symptom → cause → fix
| What you see | Likely cause | Fix |
|---|---|---|
| Blank frame / "refused to connect" | allow_iframe is false, or the origin sends
X-Frame-Options: DENY |
PATCH allow_iframe: true; allow this origin in the
app's frame-ancestors |
ERR_TOO_MANY_REDIRECTS inside the frame |
Auth cookie dropped — SameSite is Lax/Strict in a
third-party context |
Set the cookie SameSite = None (Secure + HTTPS) |
| Login page loads but never completes | Browser is blocking third-party cookies | Allow cookies for the app + *.cloudflareaccess.com;
don't test in Incognito |
| Identity check returns a CORS error | Preflight OPTIONS blocked, or
Allow-Origin/Allow-Credentials not set |
Configure CORS response in Access or bypass OPTIONS to origin |
Full write-up: docs/ACCESS_IFRAME.md in this repo.