How to get a flash message to show with passport-local logout method? - express

I am unable to show a flash message of 'You have successfully logged out' when trying to use the req.logout() method using passport-local.
Here is what I currently have, which will redirect to the login page but not display the message.
logout: (req, res, next) => {
req.logout((err) => {
if (err) {
return next(err)
}
})
req.flash('success_msg', 'You have successfully logged out')
res.redirect('/login')
}
If I comment out the req.logout code, the flash message will show up as well as redirect to the login page.
logout: (req, res, next) => {
// req.logout((err) => {
// if (err) {
// return next(err)
// }
// })
req.flash('success_msg', 'You have successfully logged out')
res.redirect('/login')
}
I am wondering how to use req.logout() and also get the flash message to show to the user.

The issue is that the req.flash() and res.redirect() needed to be inside of the req.logout() callback and in my code above it was outside of it.
logout: (req, res, next) => {
req.logout((err) => {
if (err) {
return next(err)
}
req.flash('success_msg', 'You have successfully logged out')
res.redirect('/login')
})
}

Related

How to store a property in a session with express-session?

I have the following code:
app.post("/login", (req, res) => {
const { username, password } = req.body;
// dummy local database with custome helper functions to look up a user:
db.users.findByUsername(username, (err, user) => {
if (!user) return res.status(403).json({ msg: "No user found!" });
if (user.password === password) {
// Adding properties to session
req.session.authenticated = true;
req.session.user = {
username,
password,
};
console.log(req.session);
// Session is printed in terminal with the above properties. Works fine up to here.
res.redirect("/shop");
} else {
res.status(403).json({ msg: "Bad Credentials" });
}
});
});
I used express-session to create a session and i'm storing it in memory. I created a middleware that would allow a user to access a /shop page only if they're authenticated and have the req.session.authenticated property set to true. For some reason, after they log in, and they're redirected to the /shop page, the properties created in the session are no longer there. Here's the rest of the code:
Authentication middleware:
function ensureAuthentication(req, res, next) {
if (req.session.authenticated) {
// Properties that were added upon logging in are not attached.
return next();
} else {
res.status(403).json({ msg: "You're not authorized to view this page" });
}
}
Shop page
app.get("/shop", ensureAuthentication, (req, res) => {
// Send the user object to the view page:
res.render("shop", { user: req.session.user });
});
Any opinions? Am I missing something here? Does the order of how I have the endpoints written matter?

How do I handle passport js redirects from Nuxt SSR?

I am using Nuxt SSR with express session and I have a passport JS redirect from the server side
/**
* POST /signup
* Create a new local account.
*/
exports.postSignup = (req, res, next) => {
const validationErrors = [];
if (!validator.isEmail(req.body.email)) validationErrors.push({ msg: 'Please enter a valid email address.' });
if (!validator.isLength(req.body.password, { min: 8 })) validationErrors.push({ msg: 'Password must be at least 8 characters long' });
if (req.body.password !== req.body.confirmPassword) validationErrors.push({ msg: 'Passwords do not match' });
if (validationErrors.length) {
req.flash('errors', validationErrors);
return res.redirect('/signup');
}
req.body.email = validator.normalizeEmail(req.body.email, { gmail_remove_dots: false });
const user = new User({
email: req.body.email,
password: req.body.password
});
User.findOne({ email: req.body.email }, (err, existingUser) => {
if (err) { return next(err); }
if (existingUser) {
req.flash('errors', { msg: 'Account with that email address already exists.' });
return res.redirect('/signup');
}
user.save((err) => {
if (err) { return next(err); }
req.logIn(user, (err) => {
if (err) {
return next(err);
}
res.redirect('/');
});
});
});
};
If I call the redirect method? it would reload the page and clear Vuex state right?
How do I do this redirect from passport such that Vuex state is kept intact and client page does not refresh
It is indeed better to asynchronously handle form submissions to avoid page refresh as #Darius mentioned. But for completion's sake I'd like to mention that solutions do exist to persist your Vuex state, such as vuex-persistedstate.
It can be used to persist the state to localStorage, sessionStorage, or even cookies. It can also be used as a Nuxt plugin.

Express Passportjs Authenticate not being reached in router callback

If I pass passport.authenticate("local") as middleware into my route, it executes. But this way I do not have access to res so I can send a message back to my front end. However, if I attempt to call it in the route callback function, it is not firing.
router.post("/login", function(req, res, next) {
passport.authenticate("local", function(err, user, info) {
console.log("Unreached"); // This is not logging
});
})
Here is my passport.use inside app.js
passport.use(new LocalStrategy({
usernameField: "portalId"
}, function(portalId, enteredPassword, done) {
var params = {
TableName: "MyTableName",
KeyConditionExpression : "PortalID = :portalID",
ExpressionAttributeValues : {
":portalID" : Number(portalId)
}
}
docClient.query(params, function(err, user) {
if (err) throw err;
let realPassword = user.Items[0].password;
bcrypt.compare(enteredPassword, realPassword, function(err, res) {
if (err) throw err;
if (res) {
return done(null, user);
}
if (!res) {
return done(null, false, { message: "Invalid Credentials" });
}
})
})
}));
Saw in some other post a snippet of code using the custom callback and he had (req, res, next) right after the passport.authenticate function. I added this and my code was being fired now.

User in Passport Authentication Custom Callback is always false

I'm trying to use local authentication with Passport and Express, and I have two separate routes to log in: one for the website, which does a redirect, and one for the mobile app which I want to return a JSON object. The redirect route works. However, POSTing the same username and password to the other route receives the JSON response for a failed login. My LocalStrategy is as follows:
passport.use('local-signin', new LocalStrategy(
{passReqToCallback : true},
function(req, username, password, done) {
funct.localAuth(username, password)
.then(function (user) {
if (user) {
console.log("LOGGED IN AS: " + user.username);
req.session.success = 'You are successfully logged in ' + user.username + '!';
return done(null, user);
}
if (!user) {
console.log("COULD NOT LOG IN");
req.session.error = 'Could not log user in. Please try again.'; //inform user could not log them in
return done(null, false, { message: 'User not found' });
}
})
.fail(function (err){
console.log(err.body);
return done(err);
});
}
));
and these are the two places I use it:
app.post('/login', passport.authenticate('local-signin', {
successRedirect: '/',
failureRedirect: '/signin'
})
);
app.post('/api/login', function(req, res, next) {
passport.authenticate('local-signin', function(err, user, info) {
if (err) {
return res.json(user);
}
if (!user) {
return res.json(true);
}
req.logIn(user, function(err) {
if (err) {
return next(err);
}
return res.json(user);
});
})
(req, res, next);
});
I get the success redirect from './login', but './api/login' replies with 'true' (the JSON response I have set for if 'user' is 'false'). This doesn't make any sense to me, but I can't find any problem with the code.
Any idea what the issue here could be? Thanks.

How to redirect after http basic auth to same url

I am able to bring a username and password pop up whenever i hit the url but i am able to verify the details with the one's present in database but not redirect it to same handler. It is stucking in else loop. How to do that ? After verifying if the logged in person has the right scope then it will give you response data.
My Server.js -
const simple_validate = function (request, reply, next) {
var credentials = auth(request);
if (!credentials || credentials.name !== 'john' || credentials.pass !== 'secret') {
reply('Not authorized').code(401);
reply().header('WWW-Authenticate', 'Basic realm="example"').hold();
reply('success');
} else {
next();
reply('Access granted');
}
}
server.register(Basic, (err) => {
server.auth.strategy('simple', 'basic', { validateFunc: simple_validate });
});
This is the right way of doing it.
const validate = function (request, email, password, callback) {
// validate your email and password here
User.findUser(email,password,function(err,result){
if(err)
callback(null,false);
else
//do whatever you wanna do
});
}
server.register(require('hapi-auth-basic'), (err) => {
server.auth.strategy('simple', 'basic', {
validateFunc: validateApi
});
});