Node Express - difference between req.cookies and req.session.cookie - node.js

I am trying to find out what the difference is between req.cookies and req.session.cookie. I am using Passport for authentication in Node.js Express.
If I log these two lines in my code:
console.log('cookies',req.cookies);
console.log('session',req.session);
I get this output:
cookies { 'mysite.sid.uid.whatever': 's:Ltko5IdDgsAISG0smrKNYaeIVy8nbBzF.MkGmpnf6uUKITIAgN4ws3YXqxJrMaeeSCzlKdjQnqfI' }
session { cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: false },
views: 8,
passport: {} }
I am using this configuration:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(busboyBodyParser());
//app.use(busboy());
app.use(cookieParser('cookie parser secret'));
app.use(session({
secret: process.env["SESSION_SECRET"],
saveUninitialized: true, // (default: true)
resave: true, // (default: true)
store: require('mongoose-session')(mongoose),
maxAge: 60000,
key: "mysite.sid.uid.whatever",
cookie: {secure: false}
}));
I don't really know the difference between using sessions or cookies, except that cookies are client-side only and sessions could be either client or server-side. I have read the documentation from Passport.js a few times, but I still don't really understand what is going on here. Can someone help me out with some explanation? As far as I can tell, it seems best to use server-side session using Redis. But I don't see how you can get away from using client-side data in the end. At some point, you have to rely on the client-side data stored right?
after I login with the express app, the passport object gets populated with a user field, with the MongoDB objectid.
passport: { user: 549290b8246f0e1408e48b13 } }

Typically you will be using cookies when serving browsers. The exception to this being authenticating via an HTTP header or POST parameter token, which are more typical for API requests for example.
It is true you can do client side or server side sessions using cookies, where the entire session data is stored in the cookie in the former (and does not use any storage server-side) or session data is stored server-side (with a session ID stored in a client-side cookie) in the latter.
req.cookies contains cookie values only, no matter if the cookies are session related or not. req.session.cookie contains the Set-Cookie parameters used in the client-side session ID cookie.

Related

Passport: How to use authenticated user on server1 and server2?

I want to share the passport authentication across multiple servers...
Here is my situation:
Server1: (app1.domain.com) authenticates user with passportjs local strategy. using cookie-session
Server2: (app2.domain.com), I want to leverage the user authentication from server1.
I am using the cookie-session middleware like so:
app.use(
session({
domain: `.${config.baseDomain}`,
cookie: {
path: '/',
domain: `.${config.baseDomain}` ,
maxAge: 60000,
},
secret: config.secret,
signed: true,
resave: true,
})
);
On Server1, the resulting req.session object is one line:
{ passport: { user: '5fdb8088ab37a78b980c2e6f' }
On Server2, req.session looks more similar to the req object, with hundred of lines.
I thought that using the same cookie-session middleware would mean that the req.session object would be identical?
I am trying to understand each step, because I am not sure where it is breaking.
The reason the req.session object was different on Server1 and Server2, is because of something that took me a while to track down, though it's painfully simple.
After isolating cookie-session as the culprit, I finally looked at my package.json to find servers had the different versions of cookie-session installed. (2.0Beta & 1.4.0) Once I installed v1.4.0 on both servers, everything works as expected.

Secure cookies option in Express - how to access

In a node app, I want to use cookies to read data. If I want to make a cookie using the options:
res.cookie('user', '123', { signed: true, httpOnly: true, secure: true }
and later read the cookie in a node endpoint/controller:
router.get('/test', testHandler)
function testHandler(req, res){
// how to read the secure cookie here?
}
how can I access this secure cookie on my local machine? Would I have to set up an https server locally to be able to read it?
You can just do req.session
Remember if you set the secure attribute to true, the connection has to be made over HTTPS, otherwise it won't work.

Express-session works wrong when website migrated from http to https?

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
}));

express-session secure: true

app.use(session({
secret: "testing credentials",
store: sessionStore,
resave: true,
saveUninitialized: true,
cookie : {
httpOnly: true,
//secure: true,
maxAge : 60 * 60 * 1000
}
}));
I'm working on some security problems on my newly developed website. And after done some research online, if secure=true is set, then it will be more secure. However,
If set secure: true, then information inside session will lose every time when the user send another request. Is there a way to solve this problem? If doesn't include "secure: true" in the cookie: , then the session will last for that maxAge.
If a cookie is set with the secure flag, it will only be sent to the server by the browser over https, and not plain http. This should be the default for production environments.
However, when developing an app, you probably use plain http on your dev machine. If you set your session cookie as secure in this case (using plain http), the server will never receive it, and you will experience a new empty session on each request.
So in short, you should only set the cookie as secure if you are using https (that is, in later stages of your development pipeline, and definitely in production).
On another note, if you set maxAge, the cookie will be persisted, which is not the best practice for session cookies. Without maxAge, the cookie will be kept until the user closes the browser and not normally persisted to disk, which is the correct behaviour for session cookies.

Session data lost between calls (Node/Express)

Right now my problem boils down to two servers. One node server is just serving up my static assets (HTML/JS/CSS). Another server is acting as an api - it's a rudimentary start to a microservices approach. I'm using PassportJS to handle authentication and Redis as a session storage.
When I login, I can see that my session data is being stored in req.session, but in every subsequent request, that session data is gone. The PassportJS documentation suggests that as long as I'm calling passport.initialize, the req.session.user object is created upon every request (with session data stored in the user object by invoking passport.session). However, the req.session.user object does not exist, and the only time it seems to appear is after I call req.login (and by then it has the user's data stored).
This is my middleware implementation inside the API server:
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(session(sessionConfig));
app.use(passport.initialize());
app.use(passport.session());
An example of what req.session contains after req.login is invoked
{ cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
passport: { user: <some user id> } }
What req.session contains on any request, including login prior to explicitly calling req.login
{ cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true } }
Is there something I can do to salvage all this PassportJS code? This setup seemed to work fine prior to splitting the static asset handling into it's own server. It also seemed to work fine though when I was using NGINX (which I got rid of because of my lack of comfort with a non-scripting tool) to serve up my static assets instead of a node server.
I have an inclination that I'll probably have to roll my own authentication and explicitly pass the sessionid every time I make a request from the client, but I'd prefer not to in case I'm missing something here.

Resources