Passport.authenticate, req.user and logout methods and flashes don't work on the home page


#1

I am having a weird problem with my authentication middleware. When I login, it redirects me to the home page as part of the successRedirect but doesn’t log me in actually (as there was no change in the nav). However, when I get redirected to any other page,it logs me in, displays the flash message, and as expected, the nav also changes. I experience exactly the same behaviour with logout. In the logout method, I added console logs after each line, and saw that all are logged at the same time, but it logs out only on a page different that home page.

Edit: this only happens if I redirect to the home page and not with other pages. After more checks, I see that the user isn’t sent on the req of the home page (/ route) and hence, the nav doesn’t update. If I redirect them to another page(after either login or logout), it works perfectly fine and the nav updates as well. All pages are based on the same layout.pug and the nav is also defined in that.

app.js

const express = require(`express`);
const session = require(`express-session`);
const mongoose = require(`mongoose`);
const MongoStore = require(`connect-mongo`)(session);
const path = require(`path`);
const cookieParser = require(`cookie-parser`);
const bodyParser = require(`body-parser`);
const passport = require(`passport`);
const promisify = require(`es6-promisify`);
const flash = require(`connect-flash`);
const expressValidator = require(`express-validator`);
const routes = require(`./routes/index`);
const helpers = require(`./helpers`);
const errorHandlers = require(`./handlers/errorHandlers`);
const helmet = require(`helmet`);
require(`./handlers/passport`);
require(`./handlers/mail`);

// create our Express app
const app = express();
// view engine setup
app.set(`views`, path.join(__dirname, `views`)); // this is the folder where we keep our pug files
app.set(`view engine`, `pug`); // we use the engine pug, mustache or EJS work great too

// serves up static files from the public folder. Anything in public/ will just be served up as the file it is
app.use(express.static(path.join(__dirname, `public`)));

// Use helmet

app.use(helmet());

// Takes the raw requests and turns them into usable properties on req.body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Exposes a bunch of methods for validating data. Used heavily on userController.validateRegister
app.use(expressValidator());

// populates req.cookies with any cookies that came along with the request
app.use(cookieParser());

// Sessions allow us to store data on visitors from request to request
// This keeps users logged in and allows us to send flash messages
app.use(session({
	secret: process.env.SECRET,
	key: process.env.KEY,
	resave: false,
	saveUninitialized: false,
	store: new MongoStore({ mongooseConnection: mongoose.connection })
}));

// // Passport JS is what we use to handle our logins
app.use(passport.initialize());
app.use(passport.session());

// // The flash middleware let's us use req.flash('error', 'Shit!'), which will then pass that message to the next page the user requests
app.use(flash());

// pass variables to our templates + all requests
app.use((req, res, next) => {
	res.locals.h = helpers;
	res.locals.flashes = req.flash();
	res.locals.user = req.user || null;
	res.locals.currentPath = req.path;
	next();
});

// promisify some callback based APIs
app.use((req, res, next) => {
	req.login = promisify(req.login, req);
	next();
});

// After allllll that above middleware, we finally handle our own routes!
app.use(`/`, routes);

// If that above routes didnt work, we 404 them and forward to error handler
app.use(errorHandlers.notFound);

// One of our error handlers will see if these errors are just validation errors
app.use(errorHandlers.flashValidationErrors);

// Otherwise this was a really bad error we didn't expect! Shoot eh
if (app.get(`env`) === `development`) {
	/* Development Error Handler - Prints stack trace */
	app.use(errorHandlers.developmentErrors);
}

// production error handler
app.use(errorHandlers.productionErrors);

// done! we export it so we can start the site in start.js
module.exports = app;

routes/index.js

const express = require(`express`);
const router = express.Router();

const schoolController = require(`../controllers/schoolController`);
const authController = require(`../controllers/authController`);

const { catchErrors } = require(`../handlers/errorHandlers`);

router.get(`/`, (req, res) => {
	res.render(`index`);
});

router.get(`/events`, (req, res) => {
	res.render(`events`);
});

router.get(`/register`, authController.isNotLoggedIn, schoolController.registerForm);
router.post(`/register`, schoolController.validateRegister, catchErrors(schoolController.register));

router.get(`/login`, authController.isNotLoggedIn, (req, res) => {
    res.render(`events`);
});

router.post(`/login`, authController.login);

router.get(`/logout`, catchErrors(authController.logout));

module.exports = router;

controllers/authController.js

const passport = require(`passport`);

exports.login = passport.authenticate(`local`, {
	failureRedirect: `/login`,
	failureFlash: `Failed Login!`,
	successRedirect: `/`,
	successFlash: `You are now logged in!`
});

exports.logout = async (req, res) => {
	await req.logout();
	console.log(`Logged out`);
	await req.flash(`success`, `Successfully logged out`);
	console.log(`Flashes sent`);
	await res.redirect(`/`);
	console.log(`Redirected`);
};

exports.isLoggedIn = (req, res, next) => {
	if (req.isAuthenticated()) {
		next();
		return;
	}

	req.flash(`error`, `You must be logged in to do that !!`);
	res.redirect(`/login`);
};


exports.isNotLoggedIn = (req, res, next) => {
	if (!req.isAuthenticated()) {
		next();
		return;
	}

	req.flash(`error`, `You are already logged in !!`);
	res.redirect(`/login`);
};

handlers/passport.js

const passport = require(`passport`);
const mongoose = require(`mongoose`);
const SchoolUser = mongoose.model(`SchoolUser`);

passport.use(SchoolUser.createStrategy());

passport.serializeUser(SchoolUser.serializeUser());
passport.deserializeUser(SchoolUser.deserializeUser());

What could have been the issue?