HttpFixerBlogHeaders → SameSite Cookie Issues in Iframes — Why Your Embedded App Loses Session
Headers

SameSite Cookie Issues in Iframes — Why Your Embedded App Loses Session

Updated April 2026

Reading this? Verify your fix in real-time. Scan your cookie headers → HeadersFixer

You embedded your dashboard inside a partner's page. Users are logged out the moment the iframe loads. Their browser sent the session cookie on the top-level navigation but not inside the iframe. SameSite=Lax is working as designed — blocking your embed.

Understanding the SameSite values

ValueSent on top-level navigationSent in iframes (cross-site)CSRF protection
StrictSame-site onlyNoMaximum
Lax (default)Yes (GET only)NoGood
None; SecureYesYesNone from SameSite — need CSRF tokens

The fix for embedded apps

# Cookies used inside cross-site iframes need SameSite=None
Set-Cookie: embed_session=abc123; SameSite=None; Secure; HttpOnly; Path=/

# In Chrome 2026 — also add Partitioned:
Set-Cookie: embed_session=abc123; SameSite=None; Secure; HttpOnly; Partitioned; Path=/

Implementation by framework

Express / Node.js

// Only set None for cookies that need iframe access
res.cookie("embed_session", sessionId, { sameSite: "none",  // must be lowercase string secure: true, httpOnly: true, path: "/"
});

// Session cookie stays Lax
res.cookie("session", sessionId, { sameSite: "lax", secure: true, httpOnly: true
});

FastAPI / Python

response.set_cookie( key="embed_session", value=session_id, samesite="none", secure=True, httponly=True, path="/"
)

Django

# settings.py — for embedded apps only
# Do NOT change SESSION_COOKIE_SAMESITE globally to "None"
# Set it per-cookie in your view:

response.set_cookie( "embed_session", value=session_id, samesite="None", secure=True, httponly=True
)

You also need X-Frame-Options removed (or set to SAMEORIGIN)

# If you have X-Frame-Options: DENY on your app — the iframe will be blocked entirely
# For embedded apps, either:
# 1. Remove X-Frame-Options
# 2. Set to SAMEORIGIN (allows same-domain embeds)
# 3. Use CSP frame-ancestors to allow specific partner domains:
Content-Security-Policy: frame-ancestors 'self' https://partner.com;

CSRF protection without SameSite

When you use SameSite=None, you lose CSRF protection from cookies. You need explicit CSRF tokens:

// Generate a CSRF token per session and include it in responses
// The iframe JavaScript must send it as a header with state-changing requests
app.post("/api/action", (req, res) => { const csrfToken = req.headers["x-csrf-token"]; const storedToken = req.session.csrfToken; if (!csrfToken || csrfToken !== storedToken) { return res.status(403).json({ error: "CSRF token invalid" }); } // process request
});
Scan your cookie headers → HeadersFixer
Check if your domain is on the HSTS preload list → HSTS Preload Checker