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.
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'm currently creating a Node app with Express and Passport and using this middleware in my main server.js file:
// Function to protect urls
function isProtected(req, res, next) {
if (req.isAuthenticated()) {
// User is logged in
res.locals.user = req.user;
return next();
}
// User is not logged in. Redirect to login.
res.redirect('login');
}
app.use('/protected_path', isProtected, protectedRouter);
My questions targets this line:
res.locals.user = req.user;
The user object is passed to res.locals so it can be used to populate fields like name, user role, date of registration, ...
Is there a way a user/website/api program (like Postman) can access the "res.locals" variables? There may be some sensitive data inside the req.user object and I just want to use the "res.locals" to get data which will be rendered in views like the profile page.
I could just pass the necessary variables into res.locals but this can get quite messy.
My last approach was to 'blacklist' the unnecessary variables described here: SO: How to omit specific properties from an object in JavaScript
Can the user access res.locals variables and therefore would it be security relevant? I would prefer my current solution if not.
No, they cannot access res.locals unless you give them to them yourself in a view or in some other way. Some details can be found in the documentation.
I'm using the MEAN stack with passportjs for authentication. I know I can automatically pass currentUser to every view, through this code:
app.use(function(req, res, next){
res.locals.currentUser = req.user;
next();
});
However, I also would like to access currentUser throughout my controller, for certain database queries. For example, checking whether or not a user has liked a post, before sending the relevant information to the view. Is there a similarly easy way to access currentUser in all of my different routes/controller logic?
I know I can use req.user to get the user within the logic of a route. But ideally I don't have to do var currentUser = req.user at the top of each route's logic.
Thanks in advance for your help!!
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.
I'm developing a node.js app where I'm using passport to build OAuth authentication system. I can access the user through request object in each resource load after configurating it. But my question is: How can I do to check before every URL load - resources defined with app.get('/', function(..) {...}) - if user is loged and redirect the client if it's not loged. I could do it just adding a test in every method, but this is not what I want.
Thanks!
You want a middleware that checks whether the user is logged in.
isAuthenticated = function (req, res, next) {
if (req.user)
return next(); // All good, let the route handler process the request.
else
res.redirect('/login'); // Not logged in.
}
And to use it on every route that needs to be logged in:
app.get('/something', isAuthenticated, function (req, res) {
// Only in here if the user is authenticated.
});
You can also use the middleware on every route, by doing app.use(isAuthenticated), but you will need to have extra logic in the method to not create infinite redirect loops to /login, etc.