When dealing with cookies in web development, the Domain
attribute plays a crucial role in determining cookie scope. Let's examine the technical specifications and practical implications.
RFC 2965 (now largely superseded by RFC 6265) states that cookies set with Domain=example.com
will automatically have a dot prepended, effectively becoming .example.com
. This means:
// Cookie set from subdomain.example.com
Set-Cookie: session=abc123; Domain=example.com; Path=/
// Browser interprets as:
Set-Cookie: session=abc123; Domain=.example.com; Path=/
Here's how cookie sharing actually works between domains:
// Setting cookie from subdomain that parent domain can read (PHP example)
setcookie(
"shared_cookie",
"cross_domain_value",
time() + 3600,
"/",
".example.com", // Note the leading dot
true, // Secure flag
true // HttpOnly flag
);
When working with cookies via JavaScript, you need to be explicit about the domain:
// JavaScript example for cross-subdomain cookies
document.cookie = "user_prefs=dark_mode; domain=.example.com; path=/; secure";
Developers often encounter these issues:
- Forgetting the leading dot in the domain (though modern browsers may handle this)
- Not setting the Path attribute correctly
- SSL requirements for Secure cookies
Use this simple test script to verify cookie sharing:
// Test script for cookie availability
function checkCookie() {
console.log("Cookies available:");
console.log(document.cookie);
}
// Set from subdomain
document.cookie = "test_cookie=value; domain=.example.com; path=/";
checkCookie();
When implementing cross-subdomain cookies:
- Always use the Secure flag for HTTPS sites
- Consider SameSite attributes (Strict/Lax/None)
- Be cautious with sensitive data in shared cookies
For complex cross-domain scenarios, consider:
// Using localStorage with postMessage for cross-domain communication
window.parent.postMessage({
type: 'storage',
key: 'user_token',
value: 'abc123'
}, 'https://example.com');
Remember that the exact behavior might vary slightly between browsers, so always test your implementation across different environments.
RFC 2965 (and its successor RFC 6265) creates apparent contradictions when dealing with cookie domain attributes. Here's the technical reality:
// Example of cookie setting from subdomain
Set-Cookie: shared_cookie=value; Domain=.example.com; Path=/; Secure
The actual browser behavior follows these rules:
- Explicit Domain Declaration: When subdomain.example.com sets Domain=.example.com, the cookie will be accessible to:
- subdomain.example.com
- any.other.sub.example.com
- example.com (root domain)
- Implicit Domain Handling: If no Domain is specified, modern browsers will restrict the cookie to the exact host that set it
Node.js Express Implementation
// Setting from subdomain to be accessible by root
app.get('/set-shared-cookie', (req, res) => {
res.cookie('app_token', 'xyz123', {
domain: '.example.com',
secure: true,
httpOnly: true
});
res.send('Cookie set for entire domain');
});
PHP Implementation
// PHP setcookie() example
setcookie(
"user_prefs",
json_encode($preferences),
[
'expires' => time() + 86400,
'path' => '/',
'domain' => '.example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax'
]
);
When implementing cross-subdomain cookies:
- Always use
Secure
flag for HTTPS-only transmission - Include
HttpOnly
to prevent XSS attacks - Consider
SameSite
attributes (Lax/Strict) for CSRF protection - Validate cookie scope requirements - don't over-share
Test results across major browsers (Chrome 120+, Firefox 115+, Safari 16+):
Browser | Handles .example.com | Handles example.com |
---|---|---|
Chrome | ✓ | Converts to .example.com |
Firefox | ✓ | Rejects without dot |
Safari | ✓ | Converts to .example.com |
To verify cookie behavior:
// JavaScript cookie inspection
console.log(
All cookies: ${document.cookie}\n +
Specific cookie: ${getCookie('shared_cookie')}
);
function getCookie(name) {
return document.cookie
.split('; ')
.find(row => row.startsWith(name))
?.split('=')[1];
}
Using Chrome DevTools: Application > Storage > Cookies shows exact domain scoping
Common patterns where this matters:
// Microservices architecture example
auth-service.corp.example.com → Sets auth cookie
api-service.corp.example.com → Reads auth cookie
app.example.com → Reads auth cookie