Passport: How to use authenticated user on server1 and server2? - node.js

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.

Related

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

Sharing Redis Sessions Across Node Apps

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

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.

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

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.

session persistence between sub domains

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.

Resources