0

I'm working on an express backend that uses passport-local and google-oauth2 strategies with cookie-session for authentication. The google-oauth strategy works great 100% with no issues. But my local-strategy returns req.user undefined... and req.session returns passport followed by an empty object. This directly after successfully making it to the successRedirect route!? It's as if the user is instantly logged out...

I used a few console.logs to try follow the flow of the strategy as best I can but didn't find the breaking point (find attached a link to an image of the terminal logs). terminal logs img

the code follows...

server/index.js

import 'babel-polyfill'
import express from 'express'
import mongoose from 'mongoose'
import cookieSession from 'cookie-session'
import passport from 'passport'
import bodyParser from 'body-parser'

// Import User model / making schema globaly available
import './models/User'

// Import Routes
import userRoutes from './routes/api/user'
import localAuthRoutes from './routes/auth/local'
import googleAuthRoutes from './routes/auth/google'

// Import Strategies
import './services/passportGoogle'
import './services/passportLocal'

// Config Keys
import keys from './config/keys'

mongoose.Promise = global.Promise  

// Connect to Mongodb
mongoose
  .connect(
    keys.mongoURI,
    { useMongoClient: true }
  )
  .then(() => console.log('MongoDB wired up'))
  .catch(err => console.log(err))

// Run Express
const app = express()

// Middleware
app.use(bodyParser.json())

// Passport config
app.use(
  cookieSession({
    name: 'session',
    maxAge: 30 * 24 * 60 * 60 * 1000,
    keys: [keys.cookieKey]
  })
)
app.use(passport.initialize())
app.use(passport.session())

// Use Routes
userRoutes(app)
localAuthRoutes(app)
googleAuthRoutes(app)

app.listen(5000, () => {
  console.log('Server monitoring port 5000')
})

server/routes/auth/local.js

import mongoose from 'mongoose'
import passport from 'passport'
import gravatar from 'gravatar'

import keys from '../../config/keys'
import validateRegisterInput from '../../validation/register'
import validateLoginInput from '../../validation/login'

// Import User Model
const User = mongoose.model('User')

module.exports = app => {
  // @route  POST auth/register
  // @desc   Register user with email and password
  // @access Public
  app.post('/auth/register', (req, res) => {
    const { errors, isValid } = validateRegisterInput(req.body)
    //Check Validation
    if (!isValid) {
      return res.status(400).json(errors)
    }
    // Check if User exists
    User.findOne({ email: req.body.email }).then(user => {
      if (user) {
        errors.email = 'Email alresdy in use'
        return res.status(400).json(errors)
      } else {
        const avatar = gravatar.url(req.body.email, {
          s: '200', // Size
          r: 'pg', // Rating
          d: 'mm' // Default
        })

        const newUser = new User({
          email: req.body.email,
          name: req.body.name,
          avatar,
          password: req.body.password
        })
        newUser
          .save()
          .then(user => res.json(user))
          .catch(err => console.log(err))
      }
    })
  })

  // @route  POST /auth/login
  // @desc   User Login with Eamil and Password
  // @access public
  app.post(
    '/auth/login',
    passport.authenticate('local', {
      successRedirect: '/api/success',
      failureRedirect: '/api/failed'
    })
  )
}

server/services/passportLocal.js

import passport from 'passport'
import mongoose from 'mongoose'
import { Strategy as LocalStrategy } from 'passport-local'

const User = mongoose.model('User')

passport.serializeUser((user, done) => {
  // mongoID not googleID
  console.log('reached serializeUser!')
  done(null, user.id)
})

passport.deserializeUser((id, done) => {
  // mongoID not googleID
  User.findById(id).then(user => {
    console.log('reached deserializeUser!')
    done(null, user)
  })
})

passport.use(
  new LocalStrategy(
    {
      usernameField: 'email'
    },
    async (email, password, done) => {
      const user = await User.findOne({ email: email })
      console.log('reached LocalStrategy!')

      if (!user || !user.validPassword(password)) {
        return done(null, false)
      } else {
        return done(null, user)
      }
    }
  )
)

Having no luck sorting this issue going on two days now... Any advice would be awesome!

Nico_R
  • 1
  • 1
  • check what is the value of user and user.validPassword(password) – Raj Kumar Oct 14 '18 at 20:05
  • HI Raj, thanks for the quick response and apologies for the late reply! user returns the existing users details as saved in the database. user.validPassword(password) returns true. – Nico_R Oct 16 '18 at 04:35
  • I'm sorry, cannot think of the solution. Could you just try with a fresh project having minimal code and packages used and check if that worked ? In this way you can narrow down the problem and come closer to a solution. – Raj Kumar Oct 16 '18 at 19:27

1 Answers1

0

I found a solution...! I was missing the url encoded middleware that was required for reading input key and value pairs from Postman.

Added: app.use(bodyParser.urlencoded({ extended: false })) to my root index.js file and all works now :)

Nico_R
  • 1
  • 1