Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Session cookie won't be set due to domain name mis-match, despite explicit naming

Hi,

I'm having issues understanding why my (session) cookie won't be set client-side. The error appearing on the devtools is the following:

This attempt to set a cookie via Set-Cookie header was blocked because its Domain attribute was invalid with regards to the current host url.

FaresK_1-1668298484483.png

I did a bit of researching, turns out it's a domain issue since both frontend (Firebase) and backend (Cloud run) are on different domain names.

What disturbs me, is that this issue doesn't arrive when my frontend is running on localhost (even though the backend still is remote, on cloud run).

Here's the way I configured my session:

 

  app.set('trust proxy', 1);
  app.use(json());
  app.use(
    session({
      name: '__session',
      store: new RedisStore({ client: redisClient }),
      secret: options.sessionSecret,
      resave: false,
      saveUninitialized: false,
      cookie: {
        secure: process.env.NODE_ENV === 'PROD' ? true : 'auto',
        httpOnly: true,
        maxAge: 1000 * 60 * 60 * 24 * 7,
        sameSite: process.env.NODE_ENV === 'PROD' ? 'none' : 'lax',
        domain: '<FRONTEND_URL>',
      },
    })
  );

 

I feel like the domain property is incorrect, yet I provided the frontend domain, the backend domain and the backend's root domain (run.app)

Am I missing something here? Or maybe misunderstanding something?

TIA!

0 11 19.4K
11 REPLIES 11

  • Received cookies are always stored under the front-end domain name in browser cookie storage. In case when server domain differs and cookies are saved successfully, the effect is the same as if they have been sent by the front-end domain in the first place.

  • if SameSite=None  cookie attribute is omitted today's browser (Firefox/Chrome) will use default Lax mode which is too strict for cross site cookies

  • if Secured cookie attribute is omitted - then SameSite=None will be ignored - it requires Secured to be set.

Thanks for your response Christian!

To answer your first point the main issue is that the received cookies aren't stored under the front-end's domain name.
For example, I'm using firebase hosting, so my domain name is "web.app". So I explicitly defined that domain name:

 

  app.set('trust proxy', 1);
  app.use(json());
  app.use(
    session({
      name: '__session',
      store: new RedisStore({ client: redisClient }),
      secret: options.sessionSecret,
      resave: false,
      saveUninitialized: false,
      cookie: {
        secure: process.env.NODE_ENV === 'PROD' ? true : 'auto',
        httpOnly: true,
        maxAge: 1000 * 60 * 60 * 24 * 7,
        sameSite: process.env.NODE_ENV === 'PROD' ? 'none' : 'lax',
        domain: "web.app"
      },
    })
  );

 

However the same issue was brought up: 

FaresK_0-1668810162832.png

As you can see SameSite was set to None, and Secure was provided too.

Hello Fares, I would like to know if you found the solution because I'm still facing the same problem, thank you.

Hi Raouf,

Unfortunately, I gave up. I (still) don't know where the issue came from, and stopped using Cloud Run altogether.

It's okay, unfortunately.. I can't give up, I'm gonna keep searching and I hope I will find it sooner, wish me luck

am facing the same issue after deploying my app for days now

I FOUND IT
بحمد الله وفضله

And this is the answer:

app.use(

    session({

      name: '__session',

      store: new RedisStore({ client: redisClient }),

      secret: env.Secret,

      resave: false,

      saveUninitialized: false,

      proxy: true,

      cookie: {

        same site: 'none',

        secure:true,

        httpOnly: true,

        maxAge: 1000 * 60 * 60 * 24 * 7,

      },

    })

  );

 

hey raouf, what was the fix specifically? I lm getting same domain invalid warning in browser eventhough cookie domain is set to same as my front end domain.

Work greate for me after 2hours on this bug. Thanks a lot i will see in details whats happen. but its work ❤️

You just omit specifically setting the domain? That works and the cookie gets set for me, as well, but the cookie gets set as domain: proj.web.app and I need the cookie to be set for all domains of web.app not just sub-domains of proj.web.app.

For anyone that is running into this issue I believe I have found the cause of the problem that is making the browser reject setting the cookie and a possible solution.


The cause: The domains .web.app and .run.app are on a list called the public suffix list and is considered to broad a domain so the browser rejects setting the cookie.

This is the Stack Overflow that put me onto the root of the real problem: https://stackoverflow.com/questions/74417430/session-cookie-wont-be-set-due-to-domain-name-mis-match...and you this is the link to the public suffix list: https://publicsuffix.org/. The error message given in developer tools is horrible and makes it seems like the issue is that the specified domain is different from the host URL, when the only problem is that the browser is just blocking the domain because it's on this list.

The solution: Use custom domains with your Firebase app then use Firebase Hosting rewrites that will allow you to make API calls through your custom domain and routes them to the correct Cloud Function.

Setting this up you can host your web app on URL customdomain.com and API functions, with Function Rewrites, can be sent to customdomain.com/exampleFunction. Then you'll be able to set the domain in your session cookie to customdomain.com.
Information for adding custom domains to your project can be found here: https://firebase.google.com/docs/hosting/custom-domain. Information regarding Hosting Function Rewrites can be found here: https://firebase.google.com/docs/hosting/full-config. This article helped me out a ton: https://dev.to/brianburton/cross-domain-firebase-authentication-a-simple-approach-337k. And there's a link in the article to John Carroll's original solution which is a little more in depth.