passport: Route with passport.authenticate results in bad request

I’m using passportjs with expressjs 4.12 and I’m having a bad request when trying to limit access to a route.

The following code gives a bad request

router.get('/users', passport.authenticate('local'), function(req, res) {
        res.json({ currentUser: req.user });
});

But this one works and gives me the logged in user.

router.get('/users', function(req, res) {
        res.json({ currentUser: req.user });
});

What could be wrong in the setup? The login system seems to work, the user is saved in the request session, the serialize/deserialize function from passport are called when executing the second code (without the access check).

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 34

Most upvoted comments

passport expects that in the form the names of username and password are those like that username and password, you are using pass for password, change the name in the html attributes.

I also needed body-parser with app.post. Post arguments are sent via the body, ie. req.body.

var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies

I was also facing the same issue since last night and just fixed it by adding that usernameField & passwordField keys.

       new localStrategy({
		usernameField: 'email',
		passwordField: 'password'
	}, function (email, password, done) {})

@hudsonpereira I’m not sure but I don’t think body-parser is a dependency for passportjs.

The passport-local example helped me find my error: https://github.com/jaredhanson/passport/blob/master/test/strategies/session.test.js

I had to use req.isAuthenticated() to check if the user was auth. Not make a call to passport.authenticate('local').

passport.authenticate could really use a parameter to enable debug-logging. It’s like a blackbox, and even though I know the dependencies for passport, there is no error in the console when I accidentally forgot something…

passport.authenticate(“local”) fetches username and password from the view engine.Try naming them username and password in the login form.

It’s pretty ridiculous this isn’t called out in the readme, or even an example anywhere. Getting pretty sick of the blackbox nature of passport, may switch over to permit soon

Most of the problem i get was because the lib never mention body-parser as a dependency.

It’d be helpful if this caveat was documented on passportjs.org. Would’ve saved a few hours of stress 😃

app.post('/login', (req, res) => passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login', })(req, res));

I’m running into the same problem. The passport-local documentation specifically states that you should use passport.authenticate('local'), but I’m just getting Bad Request. Any tips?

I am just going to leave this blog post here for anyone who is getting random errors and is unable to figure out how to debug : https://dmitryrogozhny.com/blog/easy-way-to-debug-passport-authentication-in-express

I wasted hours before I could try and figure out what that "Bad Request" corresponds to. It was 'Missing credentials' in my case which was because the body parser was not configured properly.

Adding the line app.use(express.json()) to my middleware fixed the problem for me, but this blog post hopefully will help others who are stuck in the crappy undescriptive message of 11 characters i.e "Bad Request" which really doesn’t tell anything.

Just replace your passport.authenticate('local') with the following:

function (req, res, next) {
    // call passport authentication passing the "local" strategy name and a callback function
    passport.authenticate('local', function (error, user, info) {
      // this will execute in any case, even if a passport strategy will find an error
      // log everything to console
      console.log(error);
      console.log(user);
      console.log(info);

      if (error) {
        res.status(401).send(error);
      } else if (!user) {
        res.status(401).send(info);
      } else {
        next();
      }

      res.status(401).send(info);
    })(req, res);
  },

There seriously needs to be a better error message for a library such widely used.

@jaredhanson would you mind making passport local log out the errors. It silently fails with a “bad request” and nothing in the logs to point out issues. The issue is that even when trying to add logging in the strategy itself, it fails before getting there: passport.use(new LocalStrategy( function(username, password, cb) { console.log('in strategy b4 db'); //never got here It’s very tough to troubleshoot because with logins you are never sure if it’s a cross site rejection, setup issue, route issue etc. I think the community would very much appreciate logging errors

I faced a similar issue. In my case, it was a wrong post body.

image

I was using form-data which results in a bad request. When i switched to x-www-form-urlencoded it works fine.

you have to named your login form input as username and password same as i write because passport authenticate look form the same data via your view engine. so if you named it as Userpassword Userusername or any other name then change it to username and password.

Thank you! it works

Most of the problem i get was because the lib never mention body-parser as a dependency.

this 4 year old reply just ended my 2 hrs of debugging lol. been debugging til i see this and used bodyparser and boom it works! thanks!

@Deepanshu088

  1. You can follow the steps that I mentioned above, this helped me determine and fix my problem : https://github.com/jaredhanson/passport/issues/371#issuecomment-513893423

  2. There is an undocumented failWithError option that you can use that might help determine the problem : https://github.com/jaredhanson/passport/issues/458#issue-131801590

Few things to check:

  • Is your username and password variable the same as the one specifieid in usernameField and passwordField? What are your username and password variable.

  • Can you check if your body parser is configured properly? That was the problem in my case. Use express’s own body parser instead of bodyParser() constructor if that’s what you are doing.

https://stackoverflow.com/questions/47232187/express-json-vs-bodyparser-json

const express = require('express');
app.use(express.json());

Hope this helps. Can you be more elaborate with your problem? Maybe share some code as well?

passport expects that in the form the names of username and password are those like that username and password, you are using pass for password, change the name in the html attributes.

You saved my life, I’m thankfull. I had to change my form names to “username” and “password” for it to work

Let’s summarise it guys. First, make sure if you’re using any json parser in you express middleware. Body-parser looks depricated, so just make sure you have this line in your code: app.use(express.json()). Second, sometimes people get 400 from passport.authenticate because of credentials. So make sure your axios requests from frontend to backend has this {withCredentials: true} as a parameter. And finally, make sure to use “username” and “password” spelled exactly like this in your userSchema, in your frontend input names, and in your strategy options. I used passport-local-mongoose, and looks like there’s no need to configure local strategy, cause it use “username” and “password” by default. Try any of this, 99% you’ll be able to authenticate user and finally move on. Later, you’ll find a way to specify “username” and “password” to be different, but for now I’m sure, your primary mission is to unstack)

The passport-local example helped me find my error: https://github.com/jaredhanson/passport/blob/master/test/strategies/session.test.js

I had to use req.isAuthenticated() to check if the user was auth. Not make a call to passport.authenticate('local').

passport.authenticate(‘local’) works if you name email/username form fields => name=“username” in the schema too.

passport expects that in the form the names of username and password are those like that username and password, you are using pass for password, change the name in the html attributes.

Thank you! changing the name of the email input from ‘email’ to ‘username’ solved my problem, the annoying part is that it’s not the first time when I make this mistake

passport expects that in the form the names of username and password are those like that username and password, you are using pass for password, change the name in the html attributes.

thank you for this advice… with advice i have solved my problem…

The doc says:

In a typical web application, the credentials used to authenticate a user will only be transmitted during the login request. If authentication succeeds, a session will be established and maintained via a cookie set in the user’s browser.

I can see in the request that the cookie is sent.

Could be something with the Local strategy? The code there seems to only check the username/password from the request. But the request is always empty.