I believe I have configured everything correctly:
app.configure(function() {
app.use(express.cookieParser('secret message')); // secret it set here in new version of express or connect
app.use(express.bodyParser());
app.use(express.session());
app.use(passport.initialize());
app.use(passport.session());
});
When the request is made to "login" with the correct credentials:
app.post('/api/login', passport.authenticate('local'), function (req, res, next) {
console.log(req.session.passport); // {"user":"5259f2739d4323000a000003"}
});
req.session.passport is populated:
"passport": {"user":"5259f2739d4323000a000003"}
However, when a call is made to:
app.post('/api/checklogin', function (req, res, next) {
console.log(req.session.passport); // {}
})
req.session.passport is lost:
"passport":{}
Both times, req.session looks like this:
{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"passport":{}}
** Passport object is obviously different though, as described above
I assume I have configured serializeUser correctly, because it correctly sets this property.
I am not completely sure how Passport creates session cookies, and how these cookies can persist.
I assume that req.session.passport is supposed to retain the user property, but it seems that the Passport object either:
Resets on every call
Does not actually save the Passport property in the session
The session is never created
I fear that I may be overlooking something large -- possibly something that I may need to do that Passport doesn't handle directly for me.
I do not know of any way to test if the session is created by Passport.
Any advice or help is really appreciated. This has been a multiple day struggle.
Are you using a cluster setup? If so, you need to stop using the default MemoryStore, and switch to something like connect-redis, so different instances of your app can access the shared session data.
Related
I've got a fairly straight forward Node Express routing app set up, to which I've just added passport.js authentication. I'm now trying to integrate this with the existing routes.
I run the basic middleware of:
app.use(passport.initialize());
app.use(passport.session());
and then if I run a simple
app.get('/route', (req, res)=>{
console.log(req.user)
});
I get the expected result of it printing the logged in user. So far so good...
However, I'm now trying to access this req.user within some of the child routes that I have set up. In the first route I'm trying the first step is to bring in a parameter and compare it against the req.user:
app.use('/route/:userId', idRouter);
And then:
idRouter.param("userId", async (req, res, next, userId) => {
console.log(userId)
console.log(req.user.id)
})
This route fires and prints out the parameter, but req.user is undefined. I can't see a reason why this is the case.
To help debug this I've put some logging in the deserialize function and I can see that it's not being called when I hit the idRouter. I can't see why this would be the case given it's inside an app.use function which should be called every time.
Help please!
I solved this in the end, it was an issue with CORS. Just needed to include credentials in API calls.
I have a MERN stack blog app that I'm making as a learning exercise. I'm relatively comfortable on the front end but have limited experience in node. I'm adding authentification after following a couple tutorials to get this far. I'm using passport.js as a framework to make a request to Google, get back an id and save as session info. However, after logging in, req.session is empty when making a post request, even though I can see a cookie in the dev tools.
I'm using bcrypt's hash to obscure the actual id, but that may not be best practice.
in blogAuth.js: req.session is defined.
bcrypt.hash(req.user._id.toString(), saltRounds, function(err, hash) {
req.session.user = hash;
//session is set here.
console.log(req.session); res.redirect(http://localhost:8080/articles/loggedIn);
});
but in api/articles.js: req.session is empty
router.post("/", (req, res, next) => {
const { body } = req;
// session is empty here. Why?
console.log(Session user, ${req.session.user});
console.log(req.session);
I have tried:
Including proxy in the client package.json:
express req.session empty with cookie-session
using withCredentials set to true when sending the POST from the
client:Node + Express + Passport: req.user Undefined
Rearranging the order of middleware: Routes must always come
afterward, but I feel like I'm doing this blindly and it usually results in an error
Here's some of the relevant files:
Server side:
- app.js
- blogAuth.js
- passport.js
- api/articles.js
Client side:
- the POST req
Entire project
I believe this is an issue with ordering. What is a good way to ensure that I order my middleware correctly? Or if the order looks correct, where else could this issue becoming from?
You are trying to use cookie-session as well as express-session. Since both of them will try to control the fate of req.session object, you will end up with empty session always.
Just remove one of them, and your session will be persisted.
Is it possible to always pass certain variables to res.render by default?
More specifically, I'm using the passport middleware that populates req.user with the current user. I need to access this on every page in my site.
It's tedious to supply it each time -- and if I forget, it appears as if the user is not logged in.
A simple solution would be to create your own middleware :
function userView(req, res, next) {
res.locals.user = req.user;
next();
}
//...
app.use(passport.initialize());
app.use(passport.session());
//...
app.use(userView);
For each request, This populates a local variable user which is then accessible to the view(s) rendered later in the chain. Activate this middleware after the passport one or req.user will be undefined.
If I am using client-sessions in NodeJS and wish to completely remove a session, how do I go about doing so? It seems that calling reset() just clears the session contents, effectively issuing a new session and updating the cookie with a new, extended expiry.
In this case, I wish to remove the session cookie altogether under certain circumstances (logout, etc.). Does anyone have any tips on how to do so?
In a router like so...
router.get('/logout', function (req, res, next) {
var session = require('client-sessions');
req.session.reset();
res.redirect('/login');
});
Try using
req.[session].reset()
where [session] is the name of your cookie.
The problem is the following: On the deployed nodejitsu app, often (not always!), when I redirect from the browser (clicks on a a href="/logout") to the /logout route, i get a req.session undefined within that route.
app.get('/logout', function(req, res){
log.debug("session", req.session); //undefined
});
The requests go through the following stack of 'middleware':
var store = new db.store({client: db.client}); // no problems here, redis monitor confirms
app.configure(function(){
[...]
app.use(express.cookieParser("XXXpassXXX"));
app.use(express.bodyParser());
app.use(express.session({
secret: "XXXpassXXX",
store: store
}));
app.use(function(req, res, next) {
var fullURL = req.protocol + "://" + req.get('host') + req.url;
if (fullURL.indexOf("logout") != -1 || fullURL[fullURL.length-1] == "/") {
log.debug(fullURL);
log.debug("sesiune", JSON.stringify(req.session)); // undefined for the "/logout" route !!!
log.debug("cookies", JSON.stringify(req.cookies));
}
next();
});
app.use(passport.session());
app.use(app.router);
});
I have checked the browser and it sends the cookies to the server and in my "logger" middleware, i can see the fullURL is correctly set.
Also, the last query made to the redis db by the app, before failing, is a get "sess:xxx" on the correct session id (which is stored in the database correctly).
Why and what could be the reasons that, after after express.session() using connect-redis as a store submits to the next() middleware, the req.session is undefined, given the fact that the session is stored on the redis database and it DOES perform a "get" on it?
PS: While on the local server, with a local redis instance, everything works.
It looks like you're doing everything right, so I'm afraid I don't have a direct answer for you. However, I hope this will help you debug the problem.
The first thing I would do is look at the various failure conditions in the session middleware, and see if any of them might be an issue in your production environment. That code is located in your project directory here:
node_modules/express/node_modules/connect/middleware/session.js
Look for the line starting with function session(options){; that's where the party starts. About 25 lines later, you'll see return function session(req, res, next){; that's the actual middleware. If you browse through that source, you'll see various reasons why the session variable might not be set (anything that throws an error or returns next()). For example, the store can be disconnected, or there's a pathname mismatch. Sometimes, debug() is called on failure, so you could try enabling debugging logging. Just set the environment variable DEBUG to express:*. I haven't used Nodejitsu yet, but I'm sure there's a way you can set environment variables and examine your logs.
If you can enable remote debugging on Nodejitsu, then even better: that way you could actually step through the session middleware and find out where it's failing (or if it's not getting called for some reason). I looked through the public Nodejitsu documentation, and didn't see anything about remote debugging, but that doesn't mean it can't be done.