36

i followed the sample of authorized-https-endpoint and only added console.log to print the req.cookies, the problem is the cookies are always empty {} I set the cookies using client JS calls and they do save but from some reason, I can't get them on the server side.

here is the full code of index.js, it's exactly the same as the sample:

'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const express = require('express');
const cookieParser = require('cookie-parser')();
const cors = require('cors')({origin: true});
const app = express();

const validateFirebaseIdToken = (req, res, next) => {
  console.log(req.cookies); //// <----- issue this is empty {} why?? 
  next();
};

app.use(cors);
app.use(cookieParser);
app.use(validateFirebaseIdToken);
app.get('/hello', (req, res) => {
  res.send(`Hello!!`);
});

exports.app = functions.https.onRequest(app);

store cookie:

curl http://FUNCTION_URL/hello --cookie "__session=bar" // req.cookies = {__session: bar}

doesn't store:

curl http://FUNCTION_URL/hello --cookie "foo=bar" // req.cookies = {}

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Sagiv Ofek
  • 25,190
  • 8
  • 60
  • 55

4 Answers4

69

If you are using Firebase Hosting + Cloud Functions, __session is the only cookie you can store, by design. This is necessary for us to be able to efficiently cache content on the CDN -- we strip all cookies from the request other than __session. This should be documented but doesn't appear to be (oops!). We'll update documentation to reflect this limitation.

Also, you need to set Cache-Control Header as private

res.setHeader('Cache-Control', 'private');
Arthur
  • 73
  • 5
Michael Bleigh
  • 25,334
  • 2
  • 79
  • 85
  • thank for letting me know. yeah, a good documentation would've saved me 2 days... I really hope you'll allow support for multiple cookies as it's pretty much a must for every modern site who uses analytics, ads, tracking etc... – Sagiv Ofek Jul 06 '17 at 01:39
  • 1
    Note: you can set cookies using Cloud Functions, and you can set and retrieve them **in the client-side JavaScript** without a problem. It is only *on the server* that you are restricted to `__session`. It shouldn't affect analytics, ads, etc. – Michael Bleigh Jul 06 '17 at 18:26
  • 10
    yeah but you do need to access cookies from server side as well usually. i get the caching restriction but it can be nice to declare the cookie names you have in the `firebase.json` config file or something so you can have more than one. – Sagiv Ofek Jul 06 '17 at 19:11
  • 1
    Seems to be now documented here: https://firebase.google.com/docs/hosting/functions#using_cookies – mjs Sep 25 '17 at 00:51
  • 1
    If you are using [express/sessions middleware](https://github.com/expressjs/session/issues/505), you would need to change the name during configuration to __session instead of the default value. ``` app.use(session({ ... name: '__session' })); ``` – Vibgy Oct 25 '17 at 17:32
  • 3
    It's also worth noting that this restriction doesn't apply when serving firebase functions locally with `firebase serve`. – leferreyra Jul 03 '18 at 21:10
  • 2
    FWIW, I had to rename my cookie name to `__session` and set the cache-control even when serving locally. Otherwise it won't work for me. – Zhi Kai Jul 21 '18 at 04:32
  • 1
    @MichaelBleigh what do you suggest we do if we are already using a cookie named `__session`? – Rich Oct 29 '18 at 14:47
  • Maybe split this cookie to store all your values there. Messy but works @Rich – dinigo Oct 31 '18 at 16:37
  • 1
    @MichaelBleigh worth noting that firebase.google.com/docs/hosting/functions#using_cookies doesn't exist anymore, but the `__session` name limitation is still lurking there – ObiWanKenobi Jun 29 '19 at 15:29
  • 1
    @restInPieces documentation now in https://firebase.google.com/docs/hosting/manage-cache#using_cookies – Kariem Jul 01 '19 at 21:07
20

Wow this cost me 2 days of debugging. It is documented (under Hosting > Serve dynamic content and host microservices > Manage cache behavior, but not in a place that I found to be useful -- it is at the very bottom "Using Cookies"). The sample code on Manage Session Cookies they provide uses the cookie name session instead of __session which, in my case, is what caused this problem for me.

Not sure if this is specific to Express.js served via cloud functions only, but that was my use case. The most frustrating part was that when testing locally using firebase serve caching doesn't factor in so it worked just fine.

ehed
  • 804
  • 1
  • 8
  • 18
  • 4
    Same... Two days of debugging. I can not get it to work locally with this method, becuase it is a totally different domain than localhost connecting to the live server (I have to use emulators to serve the function), but it works on the Firebase Hosting server. All good. – ravo10 Dec 12 '19 at 03:06
  • 6
    just want to add my 2 days of debugging here. – Urvah Shabbir Jun 08 '20 at 17:54
  • 1
    I'm facing the same error since 2 days ago. It worked for me bc my cookie was named as 'accessToken'. Thank you so much. – José Pulido Jul 31 '21 at 18:32
  • 3
    A single day of debugging for me there, but please count it as 2 as well. – Cyril Duchon-Doris Aug 18 '21 at 20:10
  • What cloud products need is a page up front called *Potential Dealbreakers*. I spent 5 days reading (and rewriting) the docs since I've learned the hard way that when choosing cloud services, it is critical to read every line because a total deal-breaker can show up anywhere. But I saved probably a couple of months in a failed Azure to Firebase migration if I hadn't obsessed over those docs. – Luke Puplett Nov 26 '21 at 12:08
1

Instead of trying req.cookies, use req.headers.cookie. You will have to handle the cookie string manually, but at least you don't need to implement express cookie parser, if that's a problem to you.

Fabio Moggi
  • 405
  • 1
  • 4
  • 12
0

Is the above answer and naming convention still valid? I can't seem to pass any cookie, to include a session cookie named "__session", to a cloud function.

I setup a simple test function, with the proper firebase rewrite rules:

export const test = functions.https.onRequest((request, response) => {

    if (request.cookies) {
        response.status(200).send(`cookies: ${request.cookies}`);
    } else {
        response.status(200).send('no cookies');
    }
});

The function gets called every time I access https://www.xxxcustomdomainxxx.com/test, but request.cookies is always undefined and thus 'no cookies' is returned.

For example, the following always returns 'no cookies':

curl https://www.xxxcustomdomainxxx.com/test --cookie "__session=testing"

I get the same behavior using the browser, even after verifying a session cookie named __session was properly set via my authentication endpoint. Further, the link cited above (https://firebase.google.com/docs/hosting/functions#using_cookies) no longer specifies anything about cookies or naming conventions.

Jack
  • 1
  • Hi Jack, could you also share what your code is doing for the middleware (the `app.use()` statements). It's possible you may not have included the cookie parser middleware. – Cameron Jun 15 '19 at 04:32
  • 2
    Cameron - Thank you. I incorrectly assumed the cloud functions api would automatically parse and populate request.cookies for each request. Prior to your comment, I wasn't using an express/cookie-parser implementation. After the quick change, it's working now. The cloud function documentation should outline specifically that request.cookies isn't automatically populated. Thanks for your response. – Jack Jun 15 '19 at 05:47