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.
Related
Is there a way to protect the api route when a user enter that in the url? Please see my screen shot. I know there's a way to authenticate a user in the backend using a middleware but it seems like if the data can be viewed publicly, the JSON payloads can also be viewed publicly. I'm still new to this, so forgive me if this question has already been asked. I use Node.js, React, Express and Sequelize.
I'm assuming that you do not want your /api/users route to be accessible to the public, I think this solution should work, although there might be better solutions.
You can try protecting specific routes based on the role of the user. I suggest you add a user_role field to your user schema, and create a middleware function that only allows logged in users with a specific role to access the route, as shown in the pseudo code below:
function (req, res, next) {
// Check if user is logged in and is assigned the role you want to allow.
if(user is logged in) return next();
else throw error;
}
I'm using express js and passport js as authentication system also using view engine. I'm looking for a solution that would give access to user and let users see their file, not the other one's file. for example, in the image folder, the user would access to their files and after that, I want to pass these files to view engine. If I use the public folder, anyone is able to see every file in there. what solution do you recommend?
You should create a directory for each users.
then, for example, your URL is /show/files
the inside your logic, filter the directory by user info.
app.get('/show/files', (req,res)=>{
// filter resources by user info
})
don't forget to create a secure URL for your resources.
Bad Idea: /images/amin/profile.png
Good Idea:
create a route to serve your resources.
app.get('/resources', (req,res)=>{
// add query parameter for resource for example profile.png
// then check user directory and send it
})
your url converts into
/resousrce?file=profile.png
I assume you already have a login system in place, so all you have to do, is create a middleware that checks if the user is logged in, and checks if the image is his image.
app.use("/user/:user/**",function(req,res){
if (req.params.user == thisuser){
//serve the file
} else {
res.status(403); //access denied
res.end();
}
//check based on cookies whether the user has the permission to view this image
});
I would suggest you to use Passport.Js local authentication. You can look into the official docs - http://www.passportjs.org/docs/authenticate/ I personally have used this in the same scenario you're in.
Here is a litte code snippet of the custom middleware function I wrote using passport -
module.exports = {
ensureAuthenticated : function(req, res, next){
if(req.isAuthenticated()){
return next();
}
req.flash('error_msg', 'Please login to view this resource.')
res.redirect('/users/login');
}
}
Feel free to check the entire solution on my github repo -
https://github.com/StechAnurag/loginsys
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!!
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.
I understand MVC structure when coding in NodeJS. I started using Keystone JS recently, and I really like it. But, the way they set their controllers up, it seems that the controllers ONLY serve the purpose of rendering a view.
In an earlier project, I had an Account.js model and an Account.js controller. I'm trying to see how it would copy over to keystone.
So: How would I allow users to signup/signin/logout in a Keystone project (not into the Admin UI, but like a member of a regular site)? How would I make an Account controller (obviously with no view to render)?
There are lots of ways you can implement your own methods of authentication and account management in keystone since it is based on express.js.
You can then add an array of 'middleware' functions to routes which will run before passing the request to the controller.
e.g
Route before middleware added
app.get('/admin', routes.views.userAdmin);
Middleware Function
function isAuthenticated(req, res, next) {
// do any checks you want to in here
// CHECK THE USER STORED IN SESSION FOR A CUSTOM VARIABLE
// you can do this however you want with whatever variables you set up
if (req.user.authenticated)
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/');
}
Route with middleware added
app.get('/admin', isAuthenticated, routes.views.userAdmin);
It's a very broad questions so I'd recommend you go and decide on the best way you'd like to do it yourself as everyone has their own personal preference. The search terms you want are 'express middleware authentication'. A lot of people use PassporJS http://passportjs.org/
Hope that helps :)