Hama Saadwn
Hama Saadwn

Reputation: 773

How to flash a message from Passport.js?

I've created login and register with express and passport js. I want to add a message for wrong password or email.

in my index.js (main) added passport and body parser middleware with referring to the routes :

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// route files
let index = require("./routes/index");
let auth = require("./routes/auth");
app.use("/", index);
app.use("/auth", auth);

and I created passport configuration :

const LocalStrategy = require("passport-local").Strategy;
const User = require("../models/User");
const config = require("../config/database");
const bcrypt = require("bcryptjs");

module.exports = function(passport) {
  // Local Strategy
  passport.use(
    new LocalStrategy(
      {
        usernameField: "email",
        passwordField: "password"
      },
      (username, password, done) => {
        // Match Email
        let query = { email: username };
        User.findOne(query, function(err, user) {
          if (err) throw err;
          if (!user) {
            return done(null, false, { message: "No user found" });
          }

          // Match Password
          bcrypt.compare(password, user.password, function(err, isMatch) {
            if (err) throw err;
            if (isMatch) {
              return done(null, user);
            } else {
              return done(null, false, { message: "Wrong password" });
            }
          });
        });
      }
    )
  );

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

  passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
      done(err, user);
    });
  });
};

also added a route for it :

// Login Process
router.post("/login", (req, res, next) => {
  passport.authenticate("local", {
    successRedirect: "/",
    failureRedirect: "/auth/login",

    failureFlash: true
  })(req, res, next);
});

the successRedirect and failureRedirect work fine, but it doesn't give me any error. I did it on a youtube video in the video it works but in my code it doesn't.

configuration of connect flash :

const flash = require("connect-flash");
app.use(require("connect-flash")());

Upvotes: 6

Views: 8067

Answers (4)

Kanmani
Kanmani

Reputation: 21

To return message without using flash option, change your post method like this

router.post('/users/signin', function (req, res, next) {
  passport.authenticate('local', function (err, user, info) {
    if (err) {
      return next(err);
    }
    if (!user) {
      // *** Display message without using flash option
      res.status(500).send({ message: info.message });
    } else {
      // *** Display message without using flash option
      res.status(200).send({ message: 'success' });
    }
  })(req, res, next);
});

Upvotes: 0

daCoda
daCoda

Reputation: 3855

Simpler route to display success / failure flash messages:

router.post('/login', passport.authenticate("local", 
    {
        successRedirect: "/",
        failureRedirect: "/auth/login",
        successFlash: true,            
        failureFlash: true,
        successFlash: 'Succesfu1!',
        failureFlash: 'Invalid username or passwerd.'
    })
);

Upvotes: 1

Asghar Musani
Asghar Musani

Reputation: 608

First, I don't quite see the point of configuring app.use() with require. Just call the flash() method inside app.use() like this in your configuration.

var flash = require("connect-flash");
app.use(flash());

What you're missing is req.flash("error"). Because when a failure occurs passport passes the message object as error.

Passport Authenticate

Setting the failureFlash option to true instructs Passport to flash an error message using the message given by the strategy's verify callback, if any.

This code is working at my end and passing req.flash() messages.

routes.js

//route for passport strategy
    router.post("/login", passport.authenticate("local-signin", {
        failureRedirect: "/error",
        failureFlash: true,
    }));

//route for error page
router.get("/error", function(req, res, next) {
    res.render("error", {
        error: req.flash("error"),
    });
});

On the view side now you have access to error object hence can use it for view. In my error.hbs handlebars view I do this.

error.hbs

{{#if error}}
    {{error}}
//Wrong password or No User Found
{{/if}}
<p>No results to show.</p>

Hope this helps.

Upvotes: 2

Saurabh Ghewari
Saurabh Ghewari

Reputation: 709

Nothing wrong with your code, its just the version of express you are using. From the Passportjs Flash Message documentation,

Note: Using flash messages requires a req.flash() function. Express 2.x provided this functionality, however it was removed from Express 3.x. Use of connect-flash middleware is recommended to provide this functionality when using Express 3.x.

So you need to install connect-flash express middleware as it is recommended.

var flash = require('connect-flash');
var app = express();

app.configure(function() {
  app.use(express.cookieParser('keyboard cat'));
  app.use(express.session({ cookie: { maxAge: 60000 }}));
  app.use(flash());
});

With the flash middleware in place, all requests will have a req.flash() function that can be used for flash messages.

app.get('/flash', function(req, res){
  req.flash('info', 'Flash is back!')
  res.redirect('/');
});

app.get('/', function(req, res){
  res.render('index', { messages: req.flash('info') });
});

This might help you.

Upvotes: 3

Related Questions