I'm just getting into MEAN-stack/general Nodejs stuff recently after years of PHP/MySQL web development and I'm looking at authentication. I used this guide to create a simple authentication server with Passport and json-server. It works exactly as described in that guide.
However, I want to be using mongoose/MongoDB for the project I'm learning with so I decided to try and alter the code in that guide to work for mongoose.
All seemed to be going fine (the '/authrequired' endpoint can't be hit without having a cookie that matches a session on the ExpressJS server and login functionality works) but I tried adding registering functionality and I'm getting a renaming error I've never seen before and can't find much information on in this context.
The registering code works fine from mongoose's point-of-view but when I try and call req.login()
which should set the session using passport and redirect to '/authrequired' (which is a guarded area requiring a session), I get kicked back to '/' (which is what happens when '/authrequired' can't authenticate the user).
The error I get is:
Error: EPERM: operation not permitted, rename 'C:\Users\admin\express-auth\server\sessions\39cad5de-5e1b-4319-b967-c77dd3ef729d.json.4139658133' -> 'C:\Users\admin\express-auth\server\sessions\39cad5de-5e1b-4319-b967-c77dd3ef729d.json'
I don't understand why express is trying to rename the session file in the first place. If I look in the sessions folder there are 2 files:
- 39cad5de-5e1b-4319-b967-c77dd3ef729d.json
- 39cad5de-5e1b-4319-b967-c77dd3ef729d.json.4139658133
The first has the json session data, the second one is blank.
Does anyone know what is going on? What have I done wrong and what can I do to resolve this?
I was not getting this renaming error using the json-server/axios version described in the linked guide.
Thanks
Passport Configuration
passport.use(new LocalStrategy(
{ usernameField: 'email' },
(email, password, done) => {
User.findOne({email: email}, (err, user) => {
if(!user) {
return done(null, false, { message: 'Invalid credentials.\n' });
}
if(!bcrypt.compareSync(password, user.password)) {
return done(null, false, { message: 'Invalid credentials.\n' });
}
return done(null, user);
});
}
});
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
if(user) {
done(null, user);
}
else if(err) {
done(error, false);
}
});
});
app setup
// create the server
const app = express();
// add & configure middleware
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(session({
genid: (req) => {
return uuid() // use UUIDs for session IDs
},
store: new FileStore(),
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}))
app.use(passport.initialize());
app.use(passport.session());
Register endpoint
app.post('/register', (req, res, next) => {
User.findOne({email: req.body.email}, (err, user) => {
if(user) {
res.send('Account with email already exists.');
} else {
console.log(req.body.password);
bcrypt.hash(req.body.password, null, null, (err, hash) => {
if(err) { return next(err); }
var newUser = new User({
username: req.body.username,
email: req.body.email,
password: hash,
passwordConf: hash
});
newUser.save((err, savedUser) => {
console.log(savedUser);
if(err) {
return res.send('error saving user.');
}
else {
req.login(savedUser, (err) => {
if(err) { return next(err); }
return res.redirect('/authrequired');
});
}
});
});
}
});
});
Login endpoint
app.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user, info) => {
if(info) {return res.send(info.message)}
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.login(user, (err) => {
if (err) { return next(err); }
return res.redirect('/authrequired');
});
})(req, res, next);
});
Authrequired endpoint
app.get('/authrequired', (req, res) => {
if(req.isAuthenticated()) {
res.send('you hit the authentication endpoint\n')
} else {
res.redirect('/')
}
});
sudo
with your command, I hope it can help. – Arpit Kumar