Express JS/ Node JS : Browsers are not setting cookie when secure=true, sameSite: 'none'
Asked Answered
D

2

18

it sets the cookie if I run the server locally, but when it is hosted online :

  1. If secure=false, sameSite: 'none' then I get the following error

Cookie “connect.sid” will be soon rejected because it has the “sameSite” attribute set to “none” or an invalid value, without the “secure” attribute. To know more about the “sameSite“ attribute, read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite

then I tried with secure=true

  1. if secure=true, sameSite: 'none' then I know it's supposed to work,

it works and the cookies are set when the server is hosted locally. But when it is hosted in heroku the cookie are not set, and I get no error.

It seems as if the client website is not secure but it shows https in the url box

What am I doing wrong here?

session config:

router.use(
    session({
        cookie: {
            secure: true,
            maxAge: 86400,
            sameSite: "none",
        },
        secret: process.env.SESSION_SECRET,
        resave: false,
        saveUninitialized: false,
    })
);

note : I have already enabled cors with credentials set to true The cookies tab was empty in the XHR cookies tab Front-end and Back-end are hosted separately in heroku XMLHttpRequest is used to send post request with withCredentials set to true.

XHRPOSThttps://sih-drs-prototype-backend-2.herokuapp.com/api/outrages/login [HTTP/1.1 200 OK 1625ms]

POST https://sih-drs-prototype-backend-2.herokuapp.com/api/outrages/login Status200 OK VersionHTTP/1.1 Transferred367 B (2 B size)

Access-Control-Allow-Credentials
    true
Access-Control-Allow-Origin
    https://tempautocomplete.herokuapp.com
Connection
    keep-alive
Content-Length
    2
Content-Type
    application/json; charset=utf-8
Date
    Sun, 12 Jul 2020 14:06:42 GMT
Etag
    W/"2-vyGp6PvFo4RvsFtPoIWeCReyIC8"
Server
    Cowboy
Vary
    Origin
Via
    1.1 vegur
X-Powered-By
    Express
    
Accept
    */*
Accept-Encoding
    gzip, deflate, br
Accept-Language
    en-US,en;q=0.5
Connection
    keep-alive
Content-Length
    46
Content-Type
    application/json;charset=UTF-8
Host
    sih-drs-prototype-backend-2.herokuapp.com
Origin
    https://tempautocomplete.herokuapp.com
Referer
    https://tempautocomplete.herokuapp.com/static/
User-Agent
    Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0
Desmond answered 12/7, 2020 at 14:9 Comment(9)
I have the same problem, I think it's because my domain doesn't have a proper SSL certificate. So the HTTPS to HTTP translate kills the cookieDilemma
edit nope setup proper ssl, still no cookie saved.Dilemma
Make sure your Access-Control-Allow-Origin on your server isn't set to a wild card *.Dilemma
Actually I found it out. The browser is indeed setting the cookie but it is not setting it in the client domain but in the server domain name. I tried setting the domain field in the express-session field but then the cookie is just rejected by the browser.Desmond
Apparently it will be seen as a invalid cookie by the browser if the cookie's domain value is different from the server's domain. developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie it's not express-session's fault, browser is the culprit. So it's better to use JWT tokens in REST APIs for authentication.Desmond
Doesn't that mean you should still be able to use 'none' with secure?Marzi
I have exactly the same issue, does anybody got any solution?Hylozoism
ANY SOLUTON ON THIS?Potentilla
Months later, same exact problem. Can't get around it.Rosenda
D
3

The problem is not with expres-session, It does its job. The browsers are not allowing cookies when the response comes from a 3rd party domain.


if you are looking for a workaround try this npm package : should-send-same-site-none https://www.npmjs.com/package/should-send-same-site-none


to be clear, the browser is not rejecting the cookies. Instead the cookies are stored in the name of the 3rd party domain name from which the response is sent.

It works perfectly fine when hosting locally since the request and the response would be from the same domain (localhost)

Desmond answered 2/9, 2020 at 13:19 Comment(7)
The issue is when I am setting the SameSIte none , yes it is getting set, but when I am setting secure : true, the code is not sending the cookie at all to the browser. Dont know what is the issue.Hylozoism
If secure is true then the cookie will be set only if the website is secure(HTTPS enabled).Desmond
Did u tried looking at xhr response in chrome? See if the cookie is received or not.Desmond
No, upon setting secure: true, chrome is not receiving cookie.Hylozoism
@Desmond can you try with HTTP only cookies, they are more secure and will save you from cross site scripting as well, in my expereince withcredentials=true & http only =true with proper CORS setting can sail you through. have a look at this article medium.com/@itsgosho2/…Ruthven
Getting error option sameSite is invalid while setting sameSite:none in response cookie options. This is because sails is using [email protected] which uses [email protected], which does not support SameSite=None option in cookies. This support was added to the cookie package in version 0.4.x. To fix it can we update express to 4.17.x, which is using [email protected].Poleax
@VELDASRDURAI, I wish that fixed it! I'm up to those version nos and am still getting no cookie in the response header when I use sameSite and secure. If I just use sameSite it creates and sends a cookie but is not allowed to be dropped.Rosenda
C
2

The settings, as posted in the original question are OK, only one thing was missing since Heroku might be using a proxy. I ran into the same problem and when I added:

app.set('trust proxy', 1);

The Set-Cookie header was finally sent from the Express server, hosted on Heroku to the browser.

Conservationist answered 14/10, 2021 at 6:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.