I know there's the following function:
function ensureAdmin(req, res, next) {
if (req.user && req.user.username === "admin") {
return next();
} else {
res.send("You do not have access to this web page. Please, contact to the system administrator.");
}
in order to ensure a page is only accessed by the admin. However, I don't find anywhere how to become a user to admin. I don't know if it is worthwhile to know, but I am using MongoDB.
Your middleware is checking a user's username to see if it is an admin.
If you want to create an admin user, in this case, you'll want to create a user whose username is 'admin' -- that user, and only that user, will be able to access any of the ensureAdmin protected routes.
Related
I have created a backend for user registration and login, I do not know how sessions are handled and verified in the back end.
I read some articles on how to generate the session token but I have no clue of how to validate that token once send to the server side asking for some information
this is what i did, stored the session in the backend for each user and then with a handmade middle-ware asked if this session is created for that user or not which i know is inefficient
router.post("/createUser",(req,res)=>{
const {Name, Email , Phone , Password, UserName} = req.body
console.log(Email,Phone,Password)
if(Name && Email && Phone && Password){
const user = new UserModel({Name,Email,Phone,Password,UserName})
user.save((e)=>e? console.log(e): console.log("success"))
const Session = new SessionModel({userID:user._id,session:req.sessionID})
Session.save()
res.status(201).send(req.sessionID)
}else{
res.status(500).send()
}
})
and this is how i validate the request
router.use("/profile",(req, res , next)=>{
const {SessionID , UserID} = req.query
SessionModel.findOne({userID:UserID},(err,session)=>{
if(session.session === SessionID){
next()
}else{
return res.status(500).send()
}
})})
router.get("/profile",(req,res)=>{
res.send("works")
})
You are quite duplicating things: express-sessions already manages sessions for you, there is no sense in duplicating those sessions into a database (express-sessions can do that for you if you have to scale beyond one server).
Actually you could just store the userID in the session, then check wether a userID exists in the session to validate the request. If you need to access the user data, you can just look the user up based on the id.
router.post("/createUser",(req,res) => {
// ...
req.session.userID = user._id;
//...
});
router.use((req, res, next) => {
if(!req.session.userID)
return res.status(403).send("not logged in");
next();
});
// all routes are secured beyond this point
Mandatory Note: Never ever store plain text passwords in your database (aka don't be like Facebook ;)). At least hash them, if you want to do it right hash them with a per user salt.
I've written code with Passport.js for authentication purpose. While user logged into chrome and using same credentials user logged into another browser 'FF'.
As we all know that Passport.js store all details into req.users and req.session.passport.users. If from one browser user update some details how can we update into another browsers req object without logout?
Same kind of, If admin update user1 details and he already logged in than how that will affect?
Any clue?
As we all know that Passport.js store all details into req.users and
Not necessarily. passport.js does not store user details in req.user, but your passport.js integration code loads the user details from some backend storage and then puts it in the request object on every request.
So it is up to you to update the user in the backend and decide when to retrieve a new version ( instead of just deserializing jwt, for example ) on every request just as well.
Sample code from http://www.passportjs.org/docs/basic-digest/
passport.use(new BasicStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.validPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
This code is executed on every single request which means that on every request to the server your user is loaded from your database.
Even if you're working with multiple sessions in multiple browsers the result is the same. So it is up to you to handle when and how you want to update your user in your database.
Otherwise if you don't load your user from an external datasource but e.g. deserialize the whole user object from jwt ( which is not recommended unless you really understand what you're doing ) then you need to think of a synchronisation strategy e.g. check some updated flag in db or some cache on deserialization
I am using Passport JS to handle authentication and Express JS to handle my routing.
Currently, I have a login route that on success go to the /teacher URI. (As shown below).
app.post('/login', passport.authenticate('local-login', {
successRedirect: '/teacher', // redirect to the teacher profile section
failureRedirect: '/login', // redirect back to the login page if there is an error
failureFlash: true // allow flash messages
}));
I have three main parts of my application, Teacher, Parent, Student.
I have built the Teacher side of the application but now looking to build the Student and Parent,
In my Passport JS session I have req.user.group which tells me if the user is a Teacher, Parent or Student.
Is there any way of redirecting to different locations dependent on what type of user logs onto the application.
E.G If a parent was to log on it would go to /parent and a student /student
Thank you.
app.post('/login', passport.authenticate('local-login', function(err, user, info){
var error = err || info;
if (error) return res.status(401).json(error);
if (!user) return res.status(404).json({message: 'Something went wrong, please try again.'});
else {
if(req.user.group==='Teacher'){
res.redirect('/teacher');
}
else if(req.user.group==='Parent'){
res.redirect('/parent');
}
else{
res.redirect('/student');
}
}
}));
Using Passport.js in Node, is there a way for me to allow one user to impersonate another? eg. as an Administrator in the application, I want to be able to log in as another user, without knowing their password.
Most simply, I would be satisfied if I could change the serialized user data (user ID) so when deserializeUser is called it will just assume the identity of the alternate user. I've tried replacing the value at req._passport.session.user and the value at req.session.passport.user but the net effect is just that my session seems to become invalid and Passport logs me out.
Passport provides a req.logIn method in case you want to do the authentication manually. You can use it to login any user even regardless of authentication.
Here's how you can use it. Have the Admin login normally, who'll have an isAdmin flag set.
Then place a middleware before passport.authenticate in your login route. This will login the new user based only on their username, if the currently logged in user isAdmin.
app.post('/login',
function forceLogin(req, res, next) {
if (!req.user.isAdmin) return next(); // skip if not admin
User.findOne({
username: req.body.username // < entered username
}, function(err, user) {
// no checking for password
req.logIn(user);
res.redirect('/users/' + user.username);
});
},
passport.authenticate('local'),
function(req, res) {
res.redirect('/users/' + req.user.username);
}
);
I have another way to impersonate, because:
I didn't want to mess with internals of authentication/passport like
session storage / logIn / etc. You must understand them really well
and also they are prone to change so I'd say it's not an option for
me.
Also, I'd like to still be able to tell if action is made from
superuser (impersonated) or normal user (not impersonated).
What I do is:
Have a route for user with superadmin role to impersonate, like /superadmin/impersonate?username=normaluser1 which sets req.user.impersonated.userid = normaluser1.userid
Then I have a middleware, which checks if user is superadmin and is impersonated:
if (req.user.isAdmin && req.user.impersonated) {
req.user.userid = req.user.impersonated.userid;
}
Also, I have found this to be a good article about user impersonation. Similar to my approach, and good for inspiration for building something similar.
The answer to your question is basically: no. The reason is this: the sessions library that is being used 99% of the time is signing the cookies, so if you tamper with the data the web server will reject it.
The way around this is to write your own passport authentication strategy that obviously doesn't do this, but I'm assuming you're talking about working with the built-in strategies here.
Hy and thanks in advance, So im working on a project, where part of the requirements, is to have a field where the user can insert is e-email, and then receive a custom url on his e-mail account, from there he can access the site. This is like the example of a "password-reset", where a custom url is generated and sent to u with a time-stamp validation. Im very new to nodejs, and my question here is if anyone has some type of guidlines to start doing this. My idea was to generate a sessionID, then generate a custom url, send the email, and then the users goes to the webpage. Im using express, and the whole site is already assembled, its just this feature tha is killing me! :(
I'm not sure what you need, but here is what I'd suggest (spoke about this on Reddit earlier).
// If you want the user to **have** to be a custom URL
req.param('userId', function(req, res, next) {
db.getUser(userId, function(e, usr) {
if (e) throw new Error(e);
req.user = usr;
});
});
req.all("*", function(req, res, next) {
if (!req.user) return res.redirect('/login');
});
// Rest of routes
req.get()
req.post()
That being said, you normally shouldn't have user login this way. Normally you would set the user in the session and validate it that way. Here's a good article on setting up sessions in Express.
If you do it this way, you would do something like this:
req.all("*", function(req, res, next) {
var userId = req.session('userid');
if (!userId) res.redirect('/login');
db.getUser(userId, function(e, usr) {
if (e) throw new Error(e);
if (!usr) return res.redirect('/login');
// Now the user is accessbile through its session
req.session.user = usr;
});
});
// Rest of routes
req.get()
req.post()
Password resetting requires what's called a nonce. This will be a small object in your DB that has a created date. You email them a link to your site that uses that nonce.
Whenever the route is hit that uses the password reset nonce, you look it up in the DB, verify it's new enough (within X hours or days), then give them access to the route that resets their password.
Your project requirements are pretty vague, so I'm not exactly sure what you need.
As of my understanding you want how to implement password reset functionality using expressjs.
Here are steps
1.
for forgot password
create an API
app.post('/forgotpassword',function(req,res){
var email = req.body.email;
// validation
// your custom url creation logic here
// someurl/:resetpasswordtoken
// store this in user data
// for this I'll suggest to use any unique string creation logic*
}
to show reset password page
app.get('/someurl/:resetpasswordtoken, function(req,res) {
//check token exist
// render the page for reset like current passwor,new password
}
Action for reset password
app.post('/someurl/:resetpasswordtoken , function(req,res){
var currentPwd = //get current pwd
var newPwd = //get new pwd
//check token
//then reset password for user
}