Session: CloudFront

Created on 18 Apr 2019  路  16Comments  路  Source: expressjs/session

Hi, I'm just trying to get my app ready for production.
The app is hosted by Aws and is built like this:
Route53 -> CloudFront -> ELB (no cluster, only SingleApp)
CloudFront is used to make the app accessible via SSL. The Nodejs app listens on an HTTP port.
Unfortunately the SessionCookie is not set.
Here is my config:

session({
            genid: (req) => {
                return uuid() // use UUIDs for session IDs
            },
            secret: process.env.SESSION_SECRET,
            resave: false,
            saveUninitialized: false,        
            proxy:!dev,    
            store: new MongoStore({ mongooseConnection: mongoose.connection }),
            rolling: true,
            cookie:{
                secure:!dev,
                httpOnly:true,
                domain:hostName,
                expires: expiryDate
            }
        })

What am I doing wrong?

Thanks for your work :smiley: .

question

Most helpful comment

Finally it works! :tada:
The solution is to select "whitelist" instead of "all" under "Cache Based on Selected Request Headers". No idea why "all" is not "all".

Under "WhiteList-Headers" the header "cloudfront-forwarded-proto" must be in the whitelist.
Bildschirmfoto vom 2019-04-22 09-04-32

Now the following middleware must be created in the Express App before the session and cookie middleware:

server.use([(req, res, next) => {
    if (req.headers['cloudfront-forwarded-proto']) {
      req.headers['x-forwarded-proto'] = req.headers['cloudfront-forwarded-proto'];
    }
    next();
  },

Many thanks for the great help @dougwilson

All 16 comments

What are the values of all those variables when it is in the non working condition?

hi, I have written the values to the variables:

const dev = process.env.NODE_ENV !== 'production';
const expiryDate = new Date( Date.now() + 60 * 60 * 1000 ); // 1 hour
session({
            genid: (req) => {
                return uuid() // use UUIDs for session IDs
            },
            secret: process.env.SESSION_SECRET, // fdsa83nfs83...........232dasdas
            resave: false,
            saveUninitialized: false,        
            proxy:!dev,    // false
            store: new MongoStore({ mongooseConnection: mongoose.connection }),
            rolling: true,
            cookie:{
                secure:!dev, // false
                httpOnly:true,
                domain:hostName, // https://app.***.de
                expires: expiryDate
            }
        })

Thank you. The only thing that jumps out at me from that is the cookie domain cannot have the https:// part on it.

No, I'm afraid not. :disappointed:
I have just tried 2 variants:
this works:

                secure:false,
                httpOnly:true,
              //  domain:hostName,
                expires: expiryDate

this not:

                secure:true,
                httpOnly:true,
              //  domain:hostName,
                expires: expiryDate

yes:

  server.enable('trust proxy');
  server.set("trust proxy", (ip)=>{
    return true;
  });

still the same :disappointed:

Is your server getting a x-forwarded-proto header with the value "https"?

No, but a x-forwarded-for, maybe this helps. The full list:

`{
"host":"mysite.eu-central-1.elasticbeanstalk.com",

"x-amz-cf-id":"abddasdas22321-3223131dads==",

"connection":"Keep-Alive",

"cookie":"_csrf=Ph1kmGT6uzslEabZ31qfuzGV; csrfToken=UxH3eyVi-EoPgnq6z4xEukc8odQhaGaKMEl4",

"user-agent":"Amazon CloudFront",

"via":"2.0 123456789abcde.cloudfront.net (CloudFront)",

"x-forwarded-for":"178.4..",

"accept-encoding":"gzip"
}`

Ah. That would prevent s secure cookie from getting set, which is the setting you have.

These are my settings :smiley: :
aws1
aws2
aws3
aws4

I'm not familiar with those settings panels, so no idea what it means.

Sorry, a misunderstanding, I thought I should send the settings. These are the cloutfront settings, maybe someone sees an error in these settings.

It's no problem. Yea, there could be one. Ultimately to set a secure cookie the connection either needs to be secure to express or reverse proxies indicate that the connection is secure with x-forwarded-proto header.

Okay, that helps a lot, thanks for your time. If I find a solution, I will post you here directly.

Finally it works! :tada:
The solution is to select "whitelist" instead of "all" under "Cache Based on Selected Request Headers". No idea why "all" is not "all".

Under "WhiteList-Headers" the header "cloudfront-forwarded-proto" must be in the whitelist.
Bildschirmfoto vom 2019-04-22 09-04-32

Now the following middleware must be created in the Express App before the session and cookie middleware:

server.use([(req, res, next) => {
    if (req.headers['cloudfront-forwarded-proto']) {
      req.headers['x-forwarded-proto'] = req.headers['cloudfront-forwarded-proto'];
    }
    next();
  },

Many thanks for the great help @dougwilson

Please open a new issue with your information. If you believe this is a similar issue you can link to it.

Was this page helpful?
0 / 5 - 0 ratings