7

When I have the following, sessions are persisted and the page counts the number of visits.

app.set('trust proxy', true)
// The documentation specifies '1' instead of 'true'

app.use(session({
   secret: 'my secret',
   proxy: true,
   resave: false,
   saveUninitialized: true,
   cookie: { secure: false }
}))

app.listen(3000, function(){
   console.log("Server is connected!");
});

app.get("/login", (req, res) => {
   if(req.session.page_views){
       req.session.page_views++;
       res.send("You visited this page " + req.session.page_views + " times");
   } else {
       req.session.page_views = 1;
       res.send("Welcome to this page for the first time!");
   }
});

However, when I remove the app.listen(3000, ...) and instead run in localhost through the command firebase serve in the CLI, sessions are not persisted.

I also tried running on production environment through firebase deploy but, again, sessions are not persisted.

I have tried multiple options on the app.use(session({ and I believe the solution might be there.

Any recommendations?

UPDATE

const express = require('express');
const session = require('express-session');
const FirestoreStore = require('firestore-store')(session);
const bodyParser = require('body-parser');

app.use(cookieParser('My secret'));
app.use(bodyParser.urlencoded({ extended: true }));

app.use(session({
    store: new FirestoreStore({
         database: firebase.firestore()
    }),
    secret: 'My secret',
    resave: true,
    saveUninitialized: true,
    cookie: {maxAge : 60000,
             secure: false,
             httpOnly: false }
}));
rgoncalv
  • 5,825
  • 6
  • 34
  • 61

2 Answers2

3

I will suggest something, instead of using this FirestoreStore, I will suggest you use this FirebaseStore.

And I noticed you're using Express, so you might want to check the usage below:

Express

NOTE: In Express 4 express-session must be passed to the function connect-session-firebase exports in order to extend express-session.Store:

const express = require('express');
const session = require('express-session');
const FirebaseStore = require('connect-session-firebase')(session);
const firebase = require('firebase-admin');
const ref = firebase.initializeApp({
  credential: firebase.credential.cert('path/to/serviceAccountCredentials.json'),
  databaseURL: 'https://databaseName.firebaseio.com'
});

express()
  .use(session({
    store: new FirebaseStore({
      database: ref.database()
    }),
    secret: 'keyboard cat'
    resave: true,
    saveUninitialized: true
  }));

And you might also want to really consider the Security provided by that dependency

If you use a publicly available Firebase Database, please set proper rules:

{
  "rules": {
    ".read": "false",
    ".write": "false",
    "sessions": {
      ".read": "false",
      ".write": "false"
    },
    "some_public_data": {
      ".read": "true",
      ".write": "auth !== null"
    }
  }
}

You can get to read more about Firebase rules and connect-session-firebase

antzshrek
  • 9,276
  • 5
  • 26
  • 43
  • I was using this beforehand and it was saving the sessions to the Realtime Database. Same problem though. In both cases, however, I didn't put credential or databaseURL in the `initializeApp()` because I always used everything I needed (Storage, Firestore) with the Admin SDK by only needing to call `initializeApp()`. I just tried to do it though following this https://firebase.google.com/docs/admin/setup#add_firebase_to_your_app and I did download the json file, but it can't seem to recognize it. How should the `path/to` be formatted? – rgoncalv Jul 04 '18 at 19:23
  • Could you try to make a sample code ( as simple as counting page views) to see if you can make it work? – rgoncalv Jul 04 '18 at 19:32
1

If you are using firebase hosting you might as well use a connector which connects your express session with firebase.

You can try connect-session-firebase middleware which will integrate the firebase database store with the current express session. This might resolve your issue regarding session persistence.

UPDATE:

If you are using firebase hosting and cloud functions then you can only set a cookie with name __session. You might have to use this name to persist sessions in firebase hosting.

app.use(session({
    store: new FirestoreStore({
         database: firebase.firestore()
    }),
    name: '__session',
    secret: 'My secret',
    resave: true,
    saveUninitialized: true,
    cookie: {maxAge : 60000,
             secure: false,
             httpOnly: false }
}));

For more info:

Abhishek Singh
  • 2,642
  • 15
  • 24
  • 1
    I've used it. It was really lacking a store. I can now see the sessions being saved in the Firebase database but still, every time I refresh the page a new session is created. It seems the browser cannot match the cookie and creates a new session. How to solve this problem? – rgoncalv Jul 04 '18 at 14:44
  • @rgoncalv open a bug request on github for it and link that to your answer. – li x Jul 04 '18 at 17:57