Security Headers & Cookie Management in Hybrid AEM CDN Setup on AWS CloudFront
Security Headers & Cookie Management in Hybrid AEM CDN Setup on AWS CloudFront
Introduction
When running a hybrid AEM setup with EDS and AMS behind a single AWS CloudFront distribution, security is more complex than a single-origin setup. You have two origins — each setting their own response headers, each with different cookie behaviour — and you need to present a consistent, secure experience to the end user regardless of which origin served the page.
Get this wrong and you end up with:
- Inconsistent Content Security Policy (CSP) headers across EDS and AMS pages
- AMS session cookies accidentally forwarded to EDS origin — destroying cache efficiency
- Security headers set by AMS Dispatcher conflicting with headers set by CloudFront
- Users losing their authenticated session when navigating from AMS pages to EDS pages
This post covers how to handle security headers and cookies correctly at the CDN layer.
The Fundamental Rule: Enforce Security Headers at CloudFront, Not at Origins
The biggest mistake teams make is trying to configure security headers independently on both origins:
- Security headers set in Apache httpd.conf on AMS Dispatcher
- Different or missing security headers on EDS (which has no Apache layer)
The result is inconsistent headers — the same CSP policy applies on /products/* but is missing or different on /blog/*.
The correct approach: enforce all security headers at CloudFront using a CloudFront Response Headers Policy. Strip security headers from both origins and let CloudFront be the single source of truth.
Both origins → CloudFront strips origin security headers
→ CloudFront Response Headers Policy applies
→ Consistent headers sent to every user
regardless of which origin served the page
Security Headers to Manage at CloudFront Level
1. Content Security Policy (CSP)
CSP is the most complex header to manage in hybrid setups because EDS and AMS may load different third-party scripts, fonts, and assets.
The challenge:
- AMS pages may load Adobe Analytics, Target, or other scripts
- EDS pages may load Google Fonts, third-party embeds
- A single CSP policy must cover both without being so permissive it becomes useless
Recommended approach:
Build a unified CSP that is a superset of what both origins need, and apply it at CloudFront level. In plain English:
Allowed script sources:
- Your own domain (self)
- Adobe Analytics / Launch domains
- Google Tag Manager
- Any third-party scripts used on either EDS or AMS pages
Allowed connect sources:
- Your API endpoints
- Adobe Experience Cloud domains
- EDS hlx.live domain (if EDS fetches resources from hlx.live)
Block:
- inline scripts (use nonces or hashes where needed)
- object-src (always block Flash/plugins)
- frame-src (whitelist only trusted embed domains)
Apply this as a CloudFront Response Headers Policy — it appends the CSP header to every response regardless of origin.
2. HSTS (HTTP Strict Transport Security)
HSTS tells browsers to always use HTTPS for your domain. This must be consistent across all paths.
Set this at CloudFront level only:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Remove it from AMS Apache/Dispatcher config entirely — if both set it, you get duplicate headers which some browsers reject.
3. X-Frame-Options and CSP frame-ancestors
Used to prevent clickjacking. Must be identical across EDS and AMS pages or the browser will behave inconsistently.
Set at CloudFront level:
X-Frame-Options: SAMEORIGIN
Or in modern setups, use CSP frame-ancestors directive instead (more flexible, replaces X-Frame-Options).
4. X-Content-Type-Options and Referrer-Policy
These are simple, consistent, and should be set once at CloudFront:
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Cookie Management — The Most Critical Part
Cookies are where hybrid setups most commonly break. AMS is a stateful system that relies heavily on cookies. EDS is completely stateless. CloudFront sits between them and must make intelligent decisions about which cookies to forward to which origin.
The Problem in Plain English
Imagine a user logs into an AMS page (/products/checkout). AEM sets a session cookie:
login-token=abc123xyz
That cookie now lives in the user's browser. When they navigate to an EDS page (/blog/latest), their browser sends the same cookie with the request to CloudFront.
If CloudFront forwards that cookie to the EDS origin:
- EDS ignores it (EDS is stateless and doesn't use cookies)
- But the cookie is now part of the CloudFront cache key
- Every authenticated user gets a different cache entry for the same EDS page
- Your CloudFront cache hit rate for EDS drops to near zero
- You are effectively serving EDS pages uncached — defeating the entire purpose of EDS
The Solution — Cookie Policies Per Cache Behaviour
In CloudFront you can define different cookie forwarding rules per path pattern.
For EDS paths — strip all cookies:
Cache Behaviour: /blog/*
Cookie forwarding: None
→ All cookies stripped before forwarding to EDS origin
→ Cache key is clean — all users share the same cache entry
→ EDS gets maximum cache efficiency
For AMS authenticated paths — forward specific cookies:
Cache Behaviour: /account/* /checkout/*
Cookie forwarding: Whitelist
Forward only: login-token, JSESSIONID
→ AMS gets the cookies it needs for authentication
→ Cache is bypassed for these paths (or keyed by cookie value)
For AMS general content paths — forward no cookies:
Cache Behaviour: /products/* /services/*
Cookie forwarding: None
→ AMS Dispatcher serves cached pages
→ No personalisation required on these paths
→ Maximum cache efficiency
SSO Across Origins — When a User Navigates Between EDS and AMS Pages
A common requirement: user logs in on an AMS page, then navigates to an EDS page. The EDS page should recognise the user is authenticated (e.g. show a personalised navigation).
The challenge: EDS cannot read AEM session cookies directly. It has no server-side session concept.
Recommended approach — JWT in a shared cookie:
User logs in on AMS (/account/login)
↓
AEM sets a lightweight JWT cookie (not the full session cookie):
user-context=eyJuYW1lIjoiQW51aiJ9
Domain: .example.com ← shared across all subpaths
HttpOnly: false ← so EDS JavaScript can read it
SameSite: Lax
↓
User navigates to EDS page (/blog/latest)
↓
EDS JavaScript reads user-context cookie
↓
Renders personalised navigation (Hello, Anuj)
This approach keeps the heavy AEM session cookie (login-token) server-side only while sharing a lightweight user context token that EDS JavaScript can use for UI personalisation.
CloudFront must be configured to:
- Not forward
user-contextto EDS origin (EDS doesn't need it at origin — it's handled client-side) - Not include
user-contextin the EDS cache key (otherwise every user gets a unique cache entry)
Duplicate Header Problem — Stripping Origin Headers at CloudFront
Both AMS Dispatcher (Apache) and CloudFront can set the same security headers. If both set them, the user's browser receives duplicate headers — which can cause unexpected behaviour or browser rejections.
Solution — strip security headers at the origin before CloudFront adds them:
On AMS Apache/Dispatcher, remove these headers from httpd.conf:
# Remove these — CloudFront will set them
# Header always set Strict-Transport-Security ...
# Header always set X-Frame-Options ...
# Header always set Content-Security-Policy ...
# Header always set X-Content-Type-Options ...
On EDS — EDS does not have an Apache layer, so there is nothing to strip. CloudFront simply adds the headers on top of the EDS response.
Summary — What Goes Where
| Header / Cookie | Managed at | Reason |
|---|---|---|
| CSP | CloudFront Response Headers Policy | Single unified policy for both origins |
| HSTS | CloudFront Response Headers Policy | Must be consistent, no duplicates |
| X-Frame-Options | CloudFront Response Headers Policy | Consistent clickjacking protection |
| X-Content-Type-Options | CloudFront Response Headers Policy | Simple, consistent |
| AMS session cookies (login-token) | Forward to AMS paths only | AMS needs them, EDS does not |
| EDS paths cookie forwarding | Strip all cookies | Protect EDS cache efficiency |
| User context JWT | Client-side only (not forwarded) | Shared identity signal for EDS JS |
Key Takeaways
- Never manage security headers independently on both origins — set them once at CloudFront and strip them from AMS Apache config entirely.
- The CSP policy must be a superset of both EDS and AMS requirements — a single policy that covers all scripts, fonts, and connections used by either origin.
- Cookie forwarding rules are the most critical configuration in hybrid setups — wrong cookie policies destroy EDS cache efficiency and can break AMS authentication.
- Use a lightweight JWT shared cookie (not the full AEM session cookie) for SSO signals between AMS and EDS pages — EDS reads it client-side without needing it at origin.
- Always use path-scoped cookie policies in CloudFront — EDS paths strip all cookies, AMS authenticated paths whitelist only what is needed.
Published on aemrules.com | Tags: AEM, EDS, AMS, CloudFront, Security Headers, CSP, Cookies, SSO, Hybrid AEM, CDN
Comments
Post a Comment