I am new to AWS. Recently, I have been trying to move one of my project's frontend and backend to AWS. I moved the backend to elastic beanstalk first. Everything is working well except the session.
The problem is that the session will be lost if I refresh the website.
I am not sure if I missed something on the session setup since it is working well in heroku.
There is one thing I am not sure is the url of the backend in elastic beanstalk. It starts with http instead of https. I have read solutions in other similar questions but none of them helped.
The code below is the session setup.
app.use(session({
resave: false,
saveUninitialized: false,
secret: 'my secret',
proxy: true,
cookie: {
secure: true,
sameSite: "None"
}
}));
app.set('trust proxy', 1);
Thank you in advanced.
The session needs to be saved persistently. You need to use a session store with persistence, (ie mongodb, MySQL,etc). Your code now is just saving it in the browser temporarily. You can check the documentation for compatible stores.
Related
EDIT - Oct 22, 2017
There was more than one reason our sessions weren't persisting, I've had to change ourexpress-session options to this:
api.use(session({
secret: 'verysecretsecret',
resave: false,
saveUninitialized: false,
cookie: {
path: '/',
httpOnly: true,
domain: 'domain.dev',
maxAge: 1000 * 60 * 24
},
store: new MongoStore({ mongooseConnection: mongoose.connection, autoReconnect: true })
}));
Apparently domain: 'localhost' causes express-session to start a new session every single time someone starts a session and then refreshes/navigates away and back when you have a seperate node instance for session handling.
I've solved this issue by doing the following:
Added 127.0.0.1 domain.dev to my hosts file located in C:\Windows\System32\drivers\etc.
I needed a place to store sessions as per the answers given below, so we chose MongoDB. This meant I had to add the following to my express-session options:store: new MongoStore({ mongooseConnection: mongoose.connection, autoReconnect: true })
Added the httpOnly: true property to the express-session options.
Because we use jQuery for our ajax requests, I had to enable some settings in the front-end web app before making calls to the back-end:$.ajaxSetup({
xhrFields: { withCredentials: true },
crossDomain: true,
});
ORIGINAL POST
I'm currently working on a platform for which was decided to have the API running on port 3001 whilst the web application itself is running on port 3000. This decision was made to make monitoring traffic more easy.
Now, we're talking about express applications so we defaulted to using the express-session npm package. I was wondering if it's at all possible to save session data stored on the node instance running on port 3001 and be retrieved by the node instance running on port 3000 if that makes sense.
To elaborate, this is our user authentication flow:
User navigates to our web app running on port 3000.
User then signs in which sends a POST request to the API running on port 3001, session data is stored when the credentials are correct, response is sent so the web app knows the user is authenticated.
User refreshes the page or comes back to the web app after closing their browser so web app loses authenticated state. So on load it always sends a GET request to the API on port 3001 to check if there's session data available, which would mean that user is logged in, so we can let the web app know user is authenticated.
(If my train of thought is at fault here, please let me know)
The problem is that express-session doesn't seem to be working when doing this.
I've enabled CORS so the web app is able to send requests to the API. And this is what the express-session configuration looks like:
api.use(session({
secret: 'verysecretsecret',
resave: false,
saveUninitialized: false,
cookie: {
path: '/',
domain: 'localhost',
maxAge: 1000 * 60 * 24
}
}));
Preferably help me solve this problem without using something like Redis, I'd simply like to know if solving this problem is possible using just express-session and node.
Preferably help me solve this problem without using something like Redis
You want us to help you solve this problem preferably without using the right tool for the job.
Without Redis you will need to use some other database. Without "something like Redis" (i.e. without a database) you will need to implement some other way to handle something that is a book example use case for a database.
And if you're going to use a database then using a database like Redis or Memcached is most reasonable for the sort of things where you need fast access to the data on pretty much every request. If you use a slower database than that, your application's performance will suffer tremendously.
I'd simply like to know if solving this problem is possible using just express-session and node.
Yes. Especially when you use express-session with Redis, as is advised in the documentation of express-session module:
https://github.com/expressjs/session#session-store-implementation
If all of your instances work on the same machine then you may be able to use a database like SQLite that stores the data in the filesystem, but even when all of your instances are on the same box, my advice would be still to use Redis as it will be much simpler and more performant, and in the case when you need to scale out it will be very easy to do.
Also if all of your session data can fit in a cookie without problems, then you can use this module:
https://www.npmjs.com/package/cookie-session
that would store all of the session data in a cookie. (Thanks to Robert Klep for pointing it out in the comments.)
After we migrated our website from http scheme to https (including enabling https on CDN and redirecting http to https on server), we found that our user sessions works incorrectly sometimes, that is, the user A would be recognized as user B! It seems the session ids of cookies are incorrectly parsed and maybe different users share the same cookies or session ids but all the session ids are generated by uid-safe uniquely.
The issue seems very strange and we really have no idea of the cause.
we use nodejs, Express, express-session with redis storage.
The express-session setup is as below:
app.use(session({
secret: 'xxxx',
cookie: {
maxAge: 3600*24*90*1000
},
store: new redisStore(),
resave: false,
rolling: true,
saveUninitialized: false
}));
I'm busy building a platform with 3 different subdomains - example.com, auth.example.com and api.example.com. They're run with 3 separate NodeJS apps running on different ports of the server.
Here is the code setting up the sessions:
var session = require("express-session");
var redisStore = require("connect-redis")(session);
var redisClient = require("redis").createClient(config.redis);
app.use(session({
secret: config.server.secret,
store: new redisStore(config.redis),
client: redisClient,
resave: false,
saveUninitialized: false,
cookie: {
domain: "example.co.za",
httpOnly: false
}
}));
The configuration is exactly the same for all 3 apps and they're sitting on the same server. For some reason, the sessions are not being shared. I seem to remember that they were being shared a few weeks back and now things are broken - I have a sneaky suspision that this happened when we moved all the traffic from HTTP to HTTPS. Would this break the sessions? I tried to turn of 'httpOnly' in case it restricted the sessions, but no luck.
I have run redid-cli MONITOR and the session is, in fact, being saved on login (Auth App) but is not being retrieved by the other app. When I turned saveUninitialized to true, the requests to save were coming from all 3 apps - this shows that they are connected to the same Redis Store.
Any help would be great.
I think this is just a cookie issue. The browser is not sending the session cookie back on your sub-domains:
you need a leading . on the domain. e.g.:
cookie: {
domain: ".example.co.za",
httpOnly: false
}
In case that doesn't work and you are having AJAX issues see this post
Got a strange issue, I am using Express and in development we use http and have secure: false for the session cookie, however now we are moving to openshift we have turned https on thinking it would be a simple endeavour but our cookies are not being sent back with the responses. If however we turn off https and revert back to http on openshift it works fine and cookies are sent.
So here is an example of what the cookie config looks like:
var setupSession = function() {
var sessionConfig = {
secret: environmentVars.cookie.secret,
name: environmentVars.cookie.name,
maxAge: environmentVars.cookie.expiry,
domain: environmentVars.cookie.domain,
httpOnly: true,
secure: environmentVars.cookie.secure, // true when using https
secureProxy: environmentVars.cookie.secure, // true when using https
signed: true
};
app.set('trust proxy', 1); // Just added this, still no luck
app.use(session(sessionConfig));
};
So the above is run when the app starts up and as noted in the comments when we are using a secure connection the environment vars are set for us, and when the above is used in conjunction with HTTPS no cookie is sent back from express, however openshift cookies are sent back, like the gears one etc. Again with http and disabling the secure stuff it works fine we all get cookies and rejoice. All responses work and data is sent back its just the set-cookie header is missing for the apps cookies (but as mentioned not openshift ones).
So the actual certificate is not setup within nodejs it is setup on openshift as an alias with a certificate applied. So express really has no idea it is being run in https other than the environmental vars it is passed and the port it is provided by the gear that is running it.
So has anyone else had anything similar or has any ideas on what we can try to solve the problem or diagnose it? I did some reading and people suggested trying the trust proxy and secureProxy, which has been done but still no luck.
So it turns out I was just being an idiot, it should look like:
var setupSession = function() {
var sessionConfig = {
secret: environmentVars.cookie.secret,
name: environmentVars.cookie.name,
maxAge: environmentVars.cookie.expiry,
domain: environmentVars.cookie.domain,
httpOnly: true,
secureProxy: environmentVars.cookie.secure, // true when using https
signed: true,
cookie: {
secure: environmentVars.cookie.secure, // true when using https
}
};
app.set('trust proxy', 1); // Just added this, still no luck
app.use(session(sessionConfig));
};
All works now :)
I had similar problem with express-session and after many trials the culprit for me was setting cookie.domain. Browsers wouldn't save the cookie.
This is how I was setting the value:
cookie: {
...
domain: process.env.OPENSHIFT_CLOUD_DOMAIN,
...
}
Hope it helps anyone going through the same, since at the time this is the best suited stackoverflow question to share this.
I am having two subdomains, api.abc.com and beta.abc.com. Both of them are on same server (box), api.abc.com is running on port 4000 and the beta.abc.com is running on 5000. I am also using node-htty-proxy to reverse proxy the requests. beta.abc.com is used to serve only static content, while api.abc.com returns the response in json.
The user authentication is done through facebook oauth on the server (api) side. Once that is done, session is created and the user is redirected to the beta. The problem I am having here is I am not able to persist sessions! I tried giving the domain option in the cookie obj (as i had seen in other questions), even that din't work.
app.use(express.session({
secret: 'omg'
, store: new mongoStore({
url: config.db.uri
, collection: 'sessions'
})
, cookie: {
domain: ".abc.com"
, maxAge: 1000*60*60*24*30*12
}
}))
How do I go about this? Am I doing anything wrong?
I found a very similar question here.