I have experienced very strange behavior of set-cookie header in request.
Tried to deal with some api 3ds calls in payments online system, when need to redirect user in another tab/window and then return in site.
And sometimes user was logged out.
Payment api send request to some /3ds route with POST
method. When i debugged this route, i saw, that cookie property in request header is lost (not in all situation, but in 1 of 10).
I tried everything and it didn't work. So i create very simple Express
app and one route /test
.
const app = express();
app.use(expressSession({
secret: 'secret',
cookie: {
maxAge: 30 * 24 * 60 * 60 * 1000,
httpOnly: true,
},
resave: true,
saveUninitialized: true
}));
app.use('/test', (req, res) => {
console.log(req.headers);
res.status(200).send();
})
And file with submit form
<html>
<body>
<form target="_blank" name="downloadForm" action="http://localhost:3000/test" method="POST"></form>
</body>
<script type="text/javascript">
const seconds = 90;
window.onload = setTimeout(() => {
submitForm();
}, seconds * 1000);
let i = 0;
setInterval(() => {
console.log(i++)
}, 1000);
function submitForm() { downloadForm.submit(); }
</script>
</html>
When seconds less then 91, then cookies present in req.headers
, and when more, cookies undefined
.
When using GET
everything works.
What cause of it?
Cookies without SameSite
attribute are treated almost as if they had SameSite=Lax
. In a strict interpretation this value means that a cookie is included in a cross-site navigation GET request, but not in a cross-site navigation POST request.
But such a strict interpretation would prevent a SAML logon flow that uses RelayState cookies, and break existing websites. For this reason, browser vendors have implemented a "Lax+POST intervention", which allows cookies without SameSite
attribute in such POST requests for a short time span (approximately two minutes). See also Why is cookie without SameSite attribute sent on cross-domain form post?. In this regard SameSite=Lax
differs from no SameSite
at all.
If you want cookies in cross-site POST navigation to be available for longer time spans, you must set the attributes SameSite=None; Secure
and serve the cookies over an HTTPS connection.