Passport + passport-local-mongoose: registration works, login always returns 401 (unauthorized)

198 Views Asked by At

Working on a MERN app, using passport / passport-local / passport-local-mongoose for user authentication and sessions. User registration works perfectly- a new user is created, a session is created, and req.session.user is set to the new user. User login creates a new session, but it doesn't login in the user or add anything to req.session.user.

I know similar questions have been asked on here- I've been going through all those questions and answers for the last three days, and nothing that's already been done works for me. It's not a CORS problem (I've set 'Access-Control-Allow-Origin' to * on all requests), my done() function is set up correctly, etc.

Relevant code:

server.js

...
const localStrategy = new LocalStrategy(
    {usernameField: 'email',
    passwordField: 'password'},
    function(username, password, done) {
        User.authenticate()(username, password, function(err, user) {
            if (err) return done(err)
            if (!user) return done(null, false)
            return done(null, user)
        })
    }

)

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

app.use(session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: true,
    store: new MongoStore({mongoUrl: process.env.MONGO_URI}),
    cookie: {
        maxAge: 1000 * 60 * 60 * 24 * 7, // 1 week
        expires: 1000 * 60 * 60 * 24 * 7, // 1 week
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'none',
    },
}))


passport.use('local', localStrategy)
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser())
app.use(passport.initialize())
app.use(passport.session())

app.post('/api/users/login', passport.authenticate('local'), (err, req, res, next) => {
  if (err) {
    res.status(203).send(err)
    next(err)
} else {
  res.status(200).send(req.user._id)}
})

app.use("/api/users", userRoutes)
...

Originally I had the login route in the userRoutes.js file, I moved it to the server in hopes that would fix things (it didn't). Here's the functional register route in userRoutes.js:

router.route('/register').post((req, res, next) => {
    User.register(
        new User({ 
          email: req.body.email, 
          username: req.body.email 
        }), req.body.password, function (err, msg) {
          if (err) {
            res.send(err)
          } else {
            passport.authenticate('local', (err, user, info) => {
                if(err) {
                    res.status(203).send(err)
                } else {
                    if(user) {
                        req.login(user, err => {
                            req.session.user = user
                            console.log(req.session)
                            res.status(200).send(user._id)
                        })
                    } else {
                        res.status(202).send(info)
                    }
                }
            })(req, res, next)

I don't have a passport.js or anything like that- all my passport setup is being done directly in server.js .

The userModel.js file is just a simple user schema.

Attemping login always returns 401 (Unauthorized).

Existing solutions on existing StackOverflow questions

  • Set CORS; already doing, works great with /register but not /login
  • Check done() function to make sure Passport is being passed the user; done
  • Make sure JWT is set up correctly - not applicable, I'm not using JWT
  • Make sure password is being decrpyted correctly; I'm not decrypting it, I'm letting passport-local-mongoose handle that (through userSchema.plugin(passportLocalMongoose).
  • Make sure passport-local is being passed 'email' in the username field- done (see my localStrategy)

AFAIK, I've tried every existing solution on here with no luck.

0

There are 0 best solutions below