Handling Third‑Party Cookie Restrictions in Chrome 80+: SameSite, HTTPS, and Node Proxy Solutions
This article explains Chrome 80+ default blocking of third‑party cookies, describes SameSite attribute options, and presents four practical solutions—including a Node.js proxy that enables cookie sharing across front‑end, proxy, and back‑end services—complete with implementation code and deployment guidance.
Background: Chrome 80+ blocks third‑party cookies by default, affecting many sites that rely on them for user tracking and authentication.
SameSite attribute options are explained: None (requires Secure), Strict (completely blocks third‑party cookies), and Lax (allows cookies on top‑level navigation GET requests).
Four solution approaches are presented: (1) Disable the restriction via Chrome settings, (2) Use an older browser version, (3) Serve the site over HTTPS and set SameSite=None, and (4) Deploy a Node.js proxy that shares cookies across the same domain and ports, requiring minimal changes to existing projects.
The proxy architecture places the front‑end project (http://127.0.0.1:8000), a Node proxy service (http://127.0.0.1:8001), and the back‑end service (http://127.0.0.1:8002) on the same host, allowing cookie sharing because cookies are domain‑based, not protocol‑ or port‑based.
Login flow: the front‑end loads an iframe pointing to the proxy, collects user credentials, and sends them via postMessage to the proxy. The proxy forwards the request to the back‑end, receives a Set‑Cookie header, writes the cookie to both its own domain and the front‑end domain, and returns the result to the front‑end page.
After successful login, both the front‑end and proxy can read the shared cookie via document.cookie. If the cookie is HttpOnly, the proxy can strip that flag before forwarding it to the front‑end.
Data queries are performed by the front‑end sending a request to the proxy with a custom _cookie header; the proxy rewrites this header to a standard Cookie header before forwarding the request to the back‑end, thus preserving authentication.
Key code snippets:
<body>
<iframe src="http://127.0.0.1:8001"></iframe> <!-- proxy service homepage providing login -->
<div>
<label>姓名:</label><input type="text" id="name" />
<br/>
<label>密码:</label><input type="password" id="pass" />
<br/>
<button id="btn-login">登录</button>
</div>
</body>
<script type="text/javascript">
var proxyHost = "http://127.0.0.1:8001";
window.onload = function() {
window.addEventListener("message", receiveMessage, false);
document.querySelector('#btn-login').addEventListener('click', function() {
window.frames[0].postMessage({
url: '/login',
payload: {
name: document.querySelector('#name').value,
pass: document.querySelector('#pass').value,
}
}, proxyHost);
}, false);
};
function receiveMessage(event) {
if (event.origin !== proxyHost) return;
if (event.data.code === 0) {
fetchUser();
}
}
function fetchUser() {
$.ajax({
type: "POST",
contentType: "application/json",
url: proxyHost + "/fetchUser",
headers: { _cookie: document.cookie },
success: function(result) { console.log('fetchUser success:', result); },
error: function(e) { console.log('fetchUser error:', e); }
});
}
</script> var appHost = "http://127.0.0.1:8000";
function login(event) {
$.ajax({
type: "POST",
contentType: "application/json",
data: JSON.stringify(event.data.payload),
url: "/login",
success: function(result) { event.source.postMessage(result, event.origin); },
error: function(e) { event.source.postMessage(e, event.origin); }
});
}
function receiveMessage(event) {
if (event.origin !== appHost) return;
if (event.data.url === '/login') { login(event); }
}
window.addEventListener("message", receiveMessage, false); const { method, headers, url } = req;
const _method = method.toLowerCase();
if (url === '/login' && _method === 'post') {
const chunks = [];
req.on('data', chunk => { chunks.push(chunk); });
req.on('end', () => {
const { name, pass } = JSON.parse(Buffer.concat(chunks).toString());
let result = { code: -1, message: 'login fail' };
const resHeaders = { 'Content-Type': 'text/json' };
if (name === '123' && pass === 'abc') {
result.code = 0;
result.message = 'login success';
resHeaders['Set-Cookie'] = `sid=abc; Max-Age=${getCookieExpires()};`;
}
res.writeHead(200, resHeaders);
res.end(JSON.stringify(result));
});
return;
}
if (url === '/fetchUser' && _method === 'post') {
if (req.headers.cookie === 'sid=abc') {
res.writeHead(200, { 'Content-Type': 'text/json' });
// return user data ...
} else {
res.writeHead(401);
res.end();
}
return;
}Conclusion: The fourth method (Node proxy) avoids modifying back‑end services and incurs low migration cost; it can be adapted for HTTPS by using the Node https module and appropriate certificates. For development, webpack dev‑server proxy can also address the issue.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Fulu Network R&D Team
Providing technical literature sharing for Fulu Holdings' tech elite, promoting its technologies through experience summaries, technology consolidation, and innovation sharing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
