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.

Loading the embedded application…
No active session? 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 seeLikely causeFix
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.