SameSite=None Cookie Compatibility Utility
This package provides a utility function (`isSameSiteNoneCompatible`) and an Express.js middleware (`shouldSendSameSiteNone`) to address specific browser compatibility issues with the `SameSite=None; Secure` cookie attribute. Introduced around Chrome 80 in February 2020, the `SameSite=None; Secure` setting is required for cross-site cookies, but some older browsers (notably Chrome 51-66, certain Safari versions, and UC Browser) handle this attribute incorrectly, potentially leading to cookies being rejected or mismanaged. This library detects these incompatible user agents based on a known list from Chromium, allowing developers to dynamically adjust cookie settings to ensure functionality across a broader range of clients. The current stable version is 2.0.5, with recent updates focused on bug fixes and improved TypeScript declarations. It offers a crucial compatibility layer for web applications relying on cross-site cookie functionality, saving developers from maintaining an exhaustive list of incompatible clients themselves.
Common errors
-
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
cause This error occurs when an Express middleware (or other code) attempts to modify HTTP headers or send a response after the HTTP response has already been sent to the client. In older versions of `should-send-same-site-none`, specifically before 2.0.5, the middleware could sometimes trigger this.fixUpdate `should-send-same-site-none` to version `2.0.5` or later. Also, ensure that your Express routes and other middleware functions send only one response per request and use `return` statements after sending a response to prevent further execution. -
Cookies with SameSite=None; Secure are not being set or sent by the browser
cause This issue typically arises for two primary reasons: either the `Secure` attribute is missing when `SameSite=None` is used (which is a modern browser requirement) or the user agent is one of the known incompatible browsers that explicitly rejects `SameSite=None`.fixEnsure all `SameSite=None` cookies are explicitly set with `secure: true`. Additionally, implement `should-send-same-site-none` to detect and handle incompatible user agents, allowing the library to remove `SameSite=None` for those specific clients, thus ensuring the cookie is still sent (potentially as `SameSite=Lax` default) and preventing rejection.
Warnings
- gotcha Cookies marked with `SameSite=None` MUST also be marked `Secure=true`. This library only handles the `SameSite` attribute compatibility and does NOT automatically add the `Secure` attribute. Failure to add `Secure` will result in browsers rejecting the cookie, regardless of `SameSite` compatibility.
- breaking In previous versions (before v2.0.5), the Express middleware could sometimes cause an `ERR_HTTP_HEADERS_SENT` error due to attempting to modify headers after they had already been sent. This typically occurred in specific scenarios where the response cycle was interrupted or completed before the middleware finished its operations.
- gotcha The core problem this library addresses is that some older browsers (Chrome 51-66, certain Safari, UC Browser) explicitly reject cookies with `SameSite=None`, treating them as invalid. Without this library, developers would need to manually maintain a list of incompatible user agents and adjust cookie settings, potentially leading to broken cross-site cookie functionality on these clients.
Install
-
npm install should-send-same-site-none -
yarn add should-send-same-site-none -
pnpm add should-send-same-site-none
Imports
- isSameSiteNoneCompatible
const isSameSiteNoneCompatible = require('should-send-same-site-none').isSameSiteNoneCompatible;import { isSameSiteNoneCompatible } from 'should-send-same-site-none'; - shouldSendSameSiteNone
const shouldSendSameSiteNone = require('should-send-same-site-none'); // Incorrect: it's a named export const { shouldSendSameSiteNone: middleware } = require('should-send-same-site-none'); // Correct for CJSimport { shouldSendSameSiteNone } from 'should-send-same-site-none'; - *
import * as SameSiteNone from 'should-send-same-site-none';
Quickstart
import express from 'express';
import { shouldSendSameSiteNone } from 'should-send-same-site-none';
const app = express();
const PORT = process.env.PORT ?? '3000';
// Apply the middleware globally before defining routes.
// This middleware will automatically remove SameSite=None from 'Set-Cookie' headers
// if the requesting client is known to be incompatible.
app.use(shouldSendSameSiteNone);
app.get('/', (req, res) => {
// When setting cross-site cookies, always set SameSite='None' and Secure=true.
// The middleware will handle exceptions for incompatible browsers.
res.cookie('session_id', 'somevalue123', { sameSite: 'none', secure: true, httpOnly: true });
res.send('Hello World! Cookie set with SameSite=None; Secure (if compatible).');
});
app.listen(Number(PORT), () => {
console.log(`Server listening on port ${PORT}`);
console.log('Try visiting with an older Chrome browser (e.g., Chrome 51-66) to see the SameSite=None attribute removed.');
});