Node.js Typeerror connect-flash - javascript

I'm having trouble showing flash messages with Node.js, Express and Connect-Flash.
I can show error messages for example, but if I want to send more than one message (e.g. a success message if an update was successful or an error message if there was a problem with the update) then I have problems.
Here's the error:
http://www.evernote.com/shard/s15/sh/5160abda-ddac-405c-9ea5-3563f3c39a02/7576bce006e47a8b1ea0346472996550
And here's snippets of my code:
// Routes.js
// ======================================
// CHANGE PASSWORD
// ======================================
app.get('/password', isLoggedIn, function (req, res) {
res.render('password', {
user: req.user, // get the user out of session and pass to template
error: req.flash('error'),
success: req.flash('success')
});
});
app.post('/password', isLoggedIn, function (req, res) {
// Save settings
if (req.body.newPassword == req.body.confirmNewPassword) {
User.findOne({_id: req.user._id}, function (err, user) {
user.local.password = generateHash(req.body.newPassword);
user.save(function(err) {
if (err)
throw new Error('There was a problem saving the password');
req.flash('success', 'Password updated successfully')
req.user = user;
res.redirect('password');
});
});
} else {
req.flash('error', 'Passwords did not match');
res.redirect('password');
}
});
// Jade template
// ===================
- if (error) // GET ERROR ON THIS LINE <------------
div.alert.alert-warning #{error}
- elseif (success)
div.alert.alert-success #{success}
Thank you!

I've fixed the problem. Here's what I did:
routes.js
// ======================================
// CHANGE PASSWORD
// ======================================
app.get('/password', isLoggedIn, function (req, res) {
var flash = req.flash();
res.render('password', {
user: req.user,
flash: flash
});
});
password.jade
if flash.error
div.alert.alert-danger #{flash.error}
else if flash.success
div.alert.alert-success #{flash.success}

Related

passport.js authenticate throwing unauthorized error?

I am trying to use passport.js with mongoose. The data sent are correct but I get an error of code 401 saying unauthorized?
Here is the back end controller.
userController.login = (req, res) =>{
console.log("recieved");
console.log(req.body);
const user = new Users({
username: req.body.mail,
password: req.body.password
})
req.login(user, (err) => {
if (err){
res.status(404).send(err);
}else{
console.log("user found");
passport.authenticate("local", (err, user, info) => {
if (err) {
return res.status(401).json(err);
}
if (user) {
return res.status(200).send(user);
} else {
res.status(401).json(info);
}
})(req, res, () => {
console.log("Authenticated!");
res.status(200).send(user);
});
}
})
}
While posting I needed to rename the req.body.mail to just req.body.username because auth and req.login looks for req body directly and search for a username object.

Getting an error: cannot set headers after they are sent to the client

I recently added authentication to my website using bcrypt. When authenticating, bcrypt compares the passwords.
If passwords match req.session is set as a cookie and written to mongodb using connect-mongodb-session. But when redirecting to /events the app crashes and gives me an error: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I'm using handlebars to render my html code
auth route:
Router.get('/', (req, res) => {
res.status(200).render('login', {pageTitle: 'Log In'});
})
Router.post('/', (req, res) => {
//Authenticate user
const username = req.body.username;
const pass = req.body.password;
User.findOne({username: username}).then((user) => {
if (user) {
//Validate password
console.log(user);
console.log(user.password);
bcrypt.compare(pass, user.password).then((doMatch) => {
console.log(doMatch);
//Check if password match
if (doMatch) {
//To use session use express-session package
req.session.isLoggedIn = true;
req.session.user = user;
req.session.save((err) => {
console.log(err);
res.redirect('/');
});
return res.redirect('/events');
} else {
res.redirect('/');
}
}).catch((err) => {
console.log(err);
});
} else {
return res.redirect('/');
}
}).catch((err) => {
console.log(err);
});
});
events route:
Router.get('/events', (req, res) => {
if (req.session.isLoggedIn) {
Event.find({}, (err, events) => {
res.render('events', {
prods: events,
pageTitle: 'Events',
path: '/events',
hasProducts: events.length > 0
});
}).catch((err) => {
console.log(err);
});
} else {
console.log('User not authenticated');
res.status(401).send('User not authenticated');
}
});
These lines are the culprit.
req.session.save((err) => {
console.log(err);
res.redirect('/');
});
return res.redirect('/events');
Here you pass a callback into save and immediately redirect res.redirect('/events').
After some time when callback redirect res.redirect('/'); throws an error.

With Express after authentication what is safer "redirect or render"?

Should i redirect or render the page? What is the best practice for authentication.
var User = require('models/user.js');
User.authenticate(req.body.email, req.body.password)
.then(function(error, user){
//IF SUCCES AND NO ERROR
res.redirect('/profile');
//OR
res.render('profile.pug');
})
.catch(error => console.log(error));
In your route you should do:
When everything is ok (no errors):
return res.render('view',{
param1:param2
});
When error appears:
req.flash('error', error.message); // If you are using flash
return res.redirect('back'); // It will redirect user back
// and display some error message
If you are going to write middleware for authentication:
middlewareObj.isAuthenticated = function(req, res, next) {
if (req.isAuthenticated()){
return next();
} else {
return res.redirect('/signin'); // Or status code
}
};

Node JS MySQL Authentication

I am new to node JS. I am working on authenticating users against backend MYSQL.
Here is the code snippet of authentication
function Authenticate(username, password, fn) {
connection.connect();
var user;
connection.query('SELECT * from Users where username = ' +
connection.escape(username) + ' and password =' + connection.escape(password),
function(err, rows) {
user = rows[0].username;
});
if (!user) {
return fn(new Error('cannot find user'));
} else {
return fn(null, user);
}
connection.end();
}
This is my call back function.
app.post('/Login', function(req, res) {
Authenticate(req.body.username, req.body.password, function(err, user) {
if (user) {
req.session.regenerate(function() {
req.session.user = user;
req.session.success = 'Authenticated as ' + user;
res.redirect('Home');
});
} else {
req.session.error = 'Authentication failed, please check your username and password.';
res.redirect('Login');
}
});
})
I am getting an error, which i cannot get my head around.
TypeError: Cannot set property 'error' of undefined
at /...../.../node_modules/app.js:42:23
at Authenticate (/..../..../node_modules/app.js:82:11).
Please share your thoughts!
Takes the else out and see if any other req.session functions properly if not check if middleware is configured correctly for express validator

How to redirect after error inside of PassportJS/Express?

When configuring passport using Express and NodeJS, I am throwing an error if the user has an invalid email address. After this error I would like to redirect to a failure page giving them instructions on how to log in correctly. Is there are a better way to do this? If not, how would I go about catching the error in some fashion and redirecting to a new page.
passport.use(new GoogleStrategy({
clientID : auth.googleAuth.clientID,
/* Settings redacted for brevity */
},
function(token, refreshToken, profile, done) {
User.findOne(
{
"google.id" : profile.id
},
function(err, user) {
if (err) return done(err)
if (user) return done(null, user)
else {
if (email.indexOf("lsmsa.edu") > -1) {
// Code redacted for brevity
} else {
done(new Error("Invalid email address"))
}
}
}
)
}))
I think you can use this:
Redirects
A redirect is commonly issued after authenticating a request.
app.post('/login',
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' }));
In this case, the redirect options override the default behavior. Upon
successful authentication, the user will be redirected to the home
page. If authentication fails, the user will be redirected back to the
login page for another attempt.
Or this:
Custom Callback
If the built-in options are not sufficient for handling an
authentication request, a custom callback can be provided to allow the
application to handle success or failure.
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
Please read the document:
https://www.passportjs.org/concepts/authentication/downloads/html/#middleware
Note: I quite like BlackMamba's answer as well, adding the custom callback / redirect is a perfectly acceptable option.
Simply add your own error handling middleware to Express:
passport.use(new GoogleStrategy({
clientID : auth.googleAuth.clientID,
/* Settings redacted for brevity */
},
function(token, refreshToken, profile, done) {
User.findOne({
"google.id" : profile.id
},
function(err, user) {
if (err) return done(err)
if (user) return done(null, user)
else {
if (email.indexOf("lsmsa.edu") > -1) {
} else {
// Throw a new error with identifier:
done(throw {
type: "invalid_email_address",
code: 401,
profileId: profile.id
}));
}
}
}
)
}));
// The error handling middleware:
app.use(function(e, req, res, next) {
if (e.type === "invalid_email_address") {
res.status(e.code).json({
error: {
msg: "Unauthorized access",
user: e.profileId
}
});
}
});
You'll notice I modified this answer a little bit with a more robust error composition. I've defined the code property of the error to match the applicable HTTP status code -- in this case, 401:
// callback
done(throw {
// just a custom object with whatever properties you want/need
type: "invalid_email_address",
code: 401,
profileId: profile.id
}));
In the error handling, we simply check the type is invalid_email_address (you can make it whatever you want, but it should be consistent across your app) and then write the error out using the "code" as the HTTP status code:
// e is the error object, and code is the custom property we defined
res.status(e.code).json({
error: {
msg: "Unauthorized access",
user: e.profileId
}
});
Here's a self-contained working example with a redirect:
var express = require('express');
var app = express();
app.all('*', function(req, res) {
throw {type: "unauthorized", code: 401}
})
app.use(function(e, req, res, next) {
console.log(e);
if (e.code === 401) {
res.redirect("/login")
} else {
res.status(500).json({error: e.type});
}
});
app.listen(9000);

Categories

Resources