Gijs Groote
Gijs Groote

Reputation: 107

passport.authenticate() does not show flash messages

Goodday,

I am following [this](https://www.youtube.com/watch?v=iX8UhDOmkPE&t=682s"Login and authenticate app") tutorial. The one difference is that I am using mysql instead mongoose.

when trying to login I want to flash messages. Such as "username not known".

Unfortunately this is not happening, also the message "credentials missing" which is hard coded in the module passport is not working.

The server.js

// modules required here

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookiesParser());
app.use(session({
secret: 'pussycat',
saveUninitialized: true,
resave: true
}));

// Express Validator
app.use(expressValidator({
    errorFormatter: function (param, msg, value) {
        var namespace = param.split('.')
        , root = namespace.shift()
        , formParam = root;

        while (namespace.length) {
            formParam += '[' + namespace.shift() + ']';
        }
        return {
            param: formParam,
            msg: msg,
            value: value
        };
    },
    customValidators: {
        myCustomFunc: function (value) {
            return false;
        }
    }
}));

/**
 * Create server
 */
http.createServer(app).listen(port);
console.log("Server listening on port " + port);

/**
 * Connect to database
 */
var connection = mysql.createConnection({
    host: "localhost",
    user: "root",
    password: "*****",
    database: '********'
});

/**
 * Print out if the connection was succesful
 */
connection.connect(function (error) {
    if (!!error) {
        console.log("Error occured while connecting to database");
    }
    else {
        console.log("Connected to Database!");
    }
});

/**
 * Serve pages and set default directory
 */
app.use(express.static(__dirname + './../client/'));

/**
 * The views to switch between on the webpage
 */
app.set("views", path.join(__dirname + './../client/views'));

/**
 * set handlebars as template view engine
 */
app.engine('handlebars', exphbs({ defaultLayout: '../../../client/views/layouts/loginLayout' }));
app.set("view engine", "handlebars");

// make sure initialize is below  serving pages and setting a default directory
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

// Global Vars
app.use(function (req, res, next) {
    res.locals.success_msg = req.flash('success_msg');
    res.locals.error_msg = req.flash('error_msg');
    res.locals.error = req.flash('error');
    res.locals.user = req.user || null;
    next();
});

/**
 * routes used for redirecting the user
 */
const routesHTML = require('./modules/Routes').htmlRoutes(app);

/**
 * functionality of logging in
 */
const login = require("./modules/Login").login(app, connection);

/**
 * Require functionality to register and create an account
 */
const register = require('./modules/Register').register(app, connection);

login module

// require modeles here

module.exports.login = function (app, connection) {

passport.use(new LocalStrategy({
    usernameField: 'usernameOrEmail', // set default to usernameOrEmail because thats how it is called client side
},
    function (username, password, done) {

        var usernamePromise = User.checkUsername(connection, username);
        var emailPromise = User.checkEmail(connection, username);


        Promise.all([emailPromise, usernamePromise]).then(function (values) {

            // check if usernameOrEmail is known mail or known username
            if (!values[0] && !values[1]) {
                console.log("should thorw error message email unknown");;
                return done(null, false, { message: 'Unknown mail or username' }); // <-- does not show client side
            }

            // create promise to retrieve user from database
            var userPromise = User.getUserByUserNameOrEmail(connection, username);
            Promise.all([userPromise]).then(function (user) {

                // enctrypt password and compare
                bcrypt.compare(password, user[0].password, function (err, result) {
                    if (!!err) {
                        console.log("Error occured when comparing the decrypted passwords");

                        return done(err, false, { message: 'Error occured when comparing the decrypted passwords' });
                    }
                    else if (result) {
                        console.log("user succesfully logged in");
                        // Everything seems to be OK!
                        return done(null, user[0]);
                    }

                    else {
                        console.log("password is not correct");
                        return done(null, false, { message: 'Invalid password' });
                    }
                });
            });

        });
    })
);



passport.serializeUser(function (user, done) {
    done(null, user.id); 
});

passport.deserializeUser(function (id, done) {
    var userPromise = User.getUserById(connection, id);
    Promise.all([userPromise]).then(function (user) {
        if(user) {
            done(null, user);
        }
        else {
            done(null, false, { message: 'No user found with this user id' 
}); 
        }
});

app.post('/login',
    passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login', failureFlash: true }),
    function (req, res) {
        console.log("this code is reachable.."); // so far not executed yet
        res.redirect('/');
    });
}  // <-- closes the " module.exports.login = function (app, connection) { "

my client side is working with .handlebars files:

 {{#if success_msg}}
    <div class="alert alert-success">{{success_msg}}</div>
    {{/if}} 

    {{#if errors}} {{#each errors}}
    <div class="alert alert-danger">{{msg}}</div>
    {{/each}} {{/if}} 

[EDIT] After a day of trial and error finally I found a way to flash my messages :)

pass req in the Localstrategy by adding:

passReqToCallback: true

This allows for req.flash('error_msg', 'Username or email not known'); 1

return done(null, false, req.flash('error_msg', 'Username or email not known'));

Because in server.js I have:

app.use(function (req, res, next) {
    res.locals.success_msg = req.flash('success_msg');
    res.locals.error_msg = req.flash('error_msg');
    res.locals.error = req.flash('error');
    res.locals.user = req.user || null;
    next();
});

the message 'Username or email not known' is shows client side in the browser

{{#if error_msg}}
<div class="alert alert-danger">{{err_msg}}</div>
{{/if}} 

Upvotes: 1

Views: 1344

Answers (1)

robertklep
robertklep

Reputation: 203419

Your middleware sets res.locals.error:

res.locals.error = req.flash('error');

But your template uses errors:

{{#if errors}} {{#each errors}}
<div class="alert alert-danger">{{msg}}</div>
{{/each}} {{/if}} 

Notice the mismatch between singular error and plural errors.

Also, I'm wondering if {{msg}} shouldn't be {{this}}.

Upvotes: 2

Related Questions