Host-Only vs Domain Cookies in CloudFront Authentication
What we learned while building the WordPress Static Site Guardian

Protecting static WordPress sites with CloudFront signed cookies — host-only cookies keep each domain secure.
Host-Only vs Domain Cookies in CloudFront Authentication
What we learned while building the WordPress Static Site Guardian
When we first built the WordPress Static Site Guardian, our stack looked straightforward:
- API Gateway + Lambda on
api.<domain>to issue CloudFront signed cookies - Static site + protected resources served from CloudFront on
<domain>
At first glance, this worked — until we ran into cookie domain scoping issues.
The Problem: Domain-Wide Cookies Collide
When the /issue-cookie Lambda sits on api.<domain>, the response often needs to include:
Set-Cookie: CloudFront-Key-Pair-Id=...; Domain=<domain>; ...
Why? Because a host-only cookie (no Domain, scoped only to the issuing host) won’t be sent with requests to <domain> if it was issued on api.<domain>.
But once you add Domain=<domain>, the cookie automatically applies to all subdomains.
That’s fine if you only ever have one site. But if you deploy the same template to both the main domain and a subdomain — each with different CloudFront key pairs and policies — the browser can attach multiple cookie triples to a single request. Suddenly, authentication breaks in subtle, hard-to-debug ways.
The Demo That Broke: wpsuite.io vs kirodev.wpsuite.io
To illustrate, here’s what actually happened during testing:
- Main site:
wpsuite.io– Cognito User Pool in us-east-1 - Demo site:
kirodev.wpsuite.io– separate User Pool in us-west-1
Each site had its own CloudFront distribution, key pair, and policy. Each also had its own signing API:
api.wpsuite.ioforwpsuite.io→ issued cookies withDomain=wpsuite.ioapi.kirodev.wpsuite.ioforkirodev.wpsuite.io→ issued cookies withDomain=kirodev.wpsuite.io
Here’s where domain scoping hit us:
- The browser correctly sent the kirodev-scoped cookie triple to
kirodev.wpsuite.io. - Additionally, because
Domain=wpsuite.iomatches all subdomains, the wpsuite-scoped cookie triple also rode along tokirodev.wpsuite.io. - When we visited
kirodev.wpsuite.io/blogor/profile, the CloudFront viewer script assumed we were authenticated — it detected CloudFront cookies. - But the CloudFront behind
kirodev.wpsuite.iorejected the request with 403, because the wrong policy and key-pair ID (from thewpsuite.iocookies) were present alongside the expected ones.
Result: the viewer script didn’t redirect us to /sign-in, and protected resources failed with 403 due to conflicting cookie triples sharing the same cookie names.
Why Host-Only Cookies Matter
- Isolation — Each subdomain can enforce its own policy without interference from broader-scoped cookies.
- Security — Host-only cookies reduce cross-site leakage across sibling subdomains.
- Correctness — CloudFront receives exactly one authoritative cookie triple per request.
Our Pivot: Lambda@Edge for Same-Domain Issuance
The fix was architectural.
Instead of issuing cookies from api.<domain>, we moved to Lambda@Edge behind a CloudFront behavior (/issue-cookie*) directly on the same <domain> that serves the protected content.
This change means:
- The
Set-Cookieheader can omit theDomainattribute. - Cookies become host-only, scoped to exactly the domain that serves the content.
- Subdomains issuing their own cookies no longer collide.
- The viewer-request Lambda@Edge now validates the Cognito JWT token directly instead of relying on IAM-protected endpoints, reducing moving parts and keeping authentication fully browser-to-Cognito. ✅
Bonus: fewer moving parts — no API Gateway endpoint to maintain — and cookie issuance happens at the edge on the same domain as the content.
Lessons Learned (and How Kiro Helped)
- Domain scoping is not a footnote — it can make or break your CloudFront auth model.
- Testing across multiple subdomains is essential; browsers happily send every matching cookie.
- Thanks to Kiro, we quickly regenerated the CloudFormation spec, pivoted the design, and re-tested end-to-end.
- The new Lambda@Edge approach is leaner, safer, and globally performant.
Takeaway for AWS Developers
If you’re protecting your CloudFront resources with signed cookies:
- Prefer host-only cookies (no
Domainattribute). - Issue cookies from the same domain that serves the protected resources (e.g., via Lambda@Edge on
<domain>/issue-cookie*). - Always test with multiple subdomains — the browser’s cookie merging behavior can surprise you.
The latest version of WordPress Static Site Guardian bakes this in, so you can deploy with confidence.
Links:
A message from our Founder
Hey, Sunil here. I wanted to take a moment to thank you for reading until the end and for being a part of this community.
Did you know that our team run these publications as a volunteer effort to over 3.5m monthly readers? We don’t receive any funding, we do this to support the community. ❤️
If you want to show some love, please take a moment to follow me on LinkedIn, TikTok, **Instagram. You can also subscribe to our [weekly newsletter](https://newsletter.plainenglish.io/)**.
And before you go, don’t forget to clap and follow the writer️!
메타데이터
- post_id
- 1d5f2dfdb7a0
- slug
- host-only-vs-domain-cookies-in-cloudfront-authentication-1d5f2dfdb7a0
- url
- https://aws.plainenglish.io/host-only-vs-domain-cookies-in-cloudfront-authentication-1d5f2dfdb7a0
- canonical_url
- https://aws.plainenglish.io/host-only-vs-domain-cookies-in-cloudfront-authentication-1d5f2dfdb7a0
- author_url
- https://medium.com/@tothl74
- status
- ok
- fetched_at
- 2026-06-16 19:09:56