Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to overwrite the "Bad Request" error message #159

Open
hagemann opened this issue Sep 9, 2017 · 4 comments
Open

How to overwrite the "Bad Request" error message #159

hagemann opened this issue Sep 9, 2017 · 4 comments

Comments

@hagemann
Copy link

hagemann commented Sep 9, 2017

Is there a way to overwrite the "Bad Request" error message if some of the required fields were not provided by the user? I would like to put something like "Required fields are missing". My current workaround is to handle such validation at the frontend.

This is related to #146

@manufacturist
Copy link

There is no way to overwrite the "Bad Request" message. After poking through the code, I've discovered that it's picked depending on the response status code.

The passport-local strategy is supposed to fail with status code 400 when the username or password are missing:

Strategy.prototype.authenticate = function(req, options) {
  options = options || {};
  // Why would one check for username and password in the query params!?
  var username = lookup(req.body, this._usernameField) || lookup(req.query, this._usernameField);
  var password = lookup(req.body, this._passwordField) || lookup(req.query, this._passwordField);
  
  if (!username || !password) {
    return this.fail({ message: options.badRequestMessage || 'Missing credentials' }, 400);
  }
[...]

Passport picks the message using the status code:

// passport/lib/middleware/authenticate.js - line ~171
if (options.failWithError) {
  return next(new AuthenticationError(http.STATUS_CODES[res.statusCode], rstatus));
}
res.end(http.STATUS_CODES[res.statusCode]);

// 400 - Bad Request

@lerit
Copy link

lerit commented Aug 1, 2018

you can do this:
passport.authenticate('local', { failWithError: true })
the fail info will pass to next ,and you can catch it.

@dhull33
Copy link

dhull33 commented Mar 9, 2019

If you are using Express and sessions, you could use connect-flash. I've used it successfully in the past by declaring the custom message when initializing the passport strategy. Here's an example using passport-local, Express, and PostgreSQL:

Initialize passport-local:

const options = {};

passport.use( 
  'local',
  new LocalStrategy(options, (username, password, done) => {
  
    // Finds user from database
    db.any('SELECT * FROM "user" WHERE username=$1', [username])
      .then((user) => {
      
        // Checks to see if user exists
        if (!user[0]) {
          return done(null, false, {
            // CUSTOM MESSAGE
            message: 'Incorrect username and password combination.'
          });
        }
        
        // Checks to see if passwords match
        if (!bcrypt.compareSync(password, user[0].password)) {
          return done(null, false, {
            // CUSTOM MESSAGE
            message: 'Incorrect username and password combination.'
          });
        }
        
        // If user exists and entered correct password, return user
        return done(null, user[0]);
      })
      .catch((err) => {
        // Triggers when there is an error with the database or query
        return done(null, false, {
          // CUSTOM MESSAGE
          message: 'There was an error!'
        });
      });
  })
);

In the route where you call passport.authenticate:

// Login Route
app.post(
  '/auth/login',
  passport.authenticate('local', {
    failureRedirect: '/',
    // Set failureFlash to true
    failureFlash: true
  }),
  (req, res) => {
    return res.redirect('/home');
  }
);

Now you'll be able to access your custom message through req.flash.

If you would like to check out the repo where I used this, you can check it out here. Anything marked with 'auth' or 'authentication' is where you'll find everything.

@abhi-nav
Copy link

abhi-nav commented Apr 14, 2019

A custom callback can be provided to allow the application to handle success or failure.

router.post('/login', (req, res, next) => {
    passport.authenticate('local', (err, user, info) => {
        if (err) return next(err); 
        
        if (!user) {
           return res.status(400).json({message: 'Required fields are missing'});
            // or return next(new Error(info.message));
        }

        // log in the user
        return res.json({
            user: req.user,
            access_token: auth.getToken(req.user), // jwt token in my case you can also use req.logIn(user, cb)
            message: 'Logged in Successful',
        });

    })(req, res, next);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants