node.jspassport.jsejsexpress-session

how to solve 'TypeError: req.isAuthenticated is not a function' error?


i am trying to create a website using nodejs, express, ejs, passportjs, express-session, etc. its a normal website but i am trying to give admin panel to add dynamic content on the website. i have given routes for admin panel. but i am getting this error when i try to get the /admin path or any path related to admin as well: TypeError: req.isAuthenticated is not a function. anyone knows how to solve it? below is my code:

app.js:

const express = require('express')
const ejsLayouts = require('express-ejs-layouts');
const cors = require('cors');
const webRoutes = require('./routes/webRoutes')
const userRoutes = require('./routes/userRoutes')

const app = express()

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
app.use(cors());

app.set('view engine', 'ejs');
app.use(ejsLayouts);



// Middleware to set currentPage variable
app.use(function(req, res, next) {
    res.locals.currentPage = req.path;
    next();
});



app.use("/", webRoutes);
app.use("/admin", userRoutes);




const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log('listening on port 3000');
});

passport-config.js:

const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')

function initialize(passport, getUserByEmail, getUserById) {
  const authenticateUser = async (email, password, done) => {
    const user = getUserByEmail(email)
    if (user == null) {
      return done(null, false, { message: 'No user with that email' })
    }

    try {
      if (await bcrypt.compare(password, user.password)) {
        return done(null, user)
      } else {
        return done(null, false, { message: 'Password incorrect' })
      }
    } catch (e) {
      return done(e)
    }
  }

  passport.use(new LocalStrategy({ usernameField: 'email' }, authenticateUser))
  passport.serializeUser((user, done) => done(null, user.id))
  passport.deserializeUser((id, done) => {
    return done(null, getUserById(id))
  })
}

module.exports = initialize

userRoutes.js:

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config()
}

const express = require('express');
const app = express();
const router = express.Router();
const bcrypt = require('bcrypt');
const passport = require('passport');
const flash = require('express-flash');
const session = require('express-session');
const methodOverride = require('method-override');

const initializePassport = require('../passport-config')
initializePassport(
    passport, 
    email => users.find(user => user.email === email),
    id => users.find(user => user.id === id)
)

const users = []


 app.use(flash())
app.use(session({
    secret: process.env.SECRET_KEY,
    resave: false,
    saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride('_method'))


// Middleware to set layout for all admin routes
router.use((req, res, next) => {
    res.locals.layout = 'layout_admin'; // Specify the admin layout
    next();
});

router.get('/', checkAuthenticated, (req, res) => {
    res.render('./admin/admin_home', {name: req.body.name});
});

router.get('/login', checkNotAutenticated, (req, res) => {
    res.render('./admin/admin_login');
});

router.post('/login', checkNotAutenticated, passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect: 'login',
    failureFlash: true
}) )

router.get('/register', checkNotAutenticated, (req, res) => {
    res.render('./admin/admin_register');
});

router.post('/register', checkNotAutenticated, async (req, res) => {

    try {
        const hashedPass = await bcrypt.hash(req.body.password, 10)
        users.push({
            id: Date.now().toString(),
            name: req.body.name,
            email: req.body.email,
            password: hashedPass
        })

        res.redirect('login')
    } catch (err) {
        res.redirect('register')
    }
    console.log(users)
});

router.delete('/logout', (req, res) => {
    req.logOut()
    res.redirect('login')
})

function checkAuthenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return next()
    }

    res.redirect('login')
}

function checkNotAutenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return res.redirect('/')
    }
    next()

}

module.exports = router;

Solution

  • In the userRoutes, you're using both app and router, and passport is loaded in app, not router, so the router doesn't have passport middleware loaded, hence the error, because it's undefined.

    So, in userRoutes just use router throughout instead of app, and load middleware in it:

    const express = require('express');
    const router = express.Router();
        
    //...
    
    router.use(flash())
    router.use(session({
        secret: process.env.SECRET_KEY,
        resave: false,
        saveUninitialized: false
    }))
    router.use(passport.initialize())
    router.use(passport.session())
    router.use(methodOverride('_method'))
    
    //...
    

    router docs: express.Router