Passport.js not removing session on req.logout() - node.js

I also tried req.session.destroy() but it throws me an error saying => Error: req.flash() requires sessions.
// Logout route
router.get('/logout' , (req , res) => {
req.logOut();
// req.session.destroy();
req.flash('success_msg' , 'You are successfully logged out');
res.redirect('/users/login');
})
module.exports = router;
require part of app.js
const express = require('express');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
const path = require('path');
const mongoose = require('mongoose');
const methodOverride = require('method-override');
const flash = require('connect-flash');
const session = require('express-session');
require('./config/passport')(passport);
const db = require('./config/database');
middleware of app.js
handlebar middleware
app.engine('handlebars', exphbs({
defaultLayout: 'main'
}));
express session middleware
app.use(
session({
secret: "my secret",
resave: true,
saveUninitialized: true
})
);
app.set('view engine', 'handlebars');
passport
app.use(passport.initialize());
app.use(passport.session());
flash middleware
app.use(flash());

Related

Cannot authenticate user with Passport Local Strategy

I am using passport to implement a login function on my application. However, every time I try to authenticate the user, I cannot get passed the authentication and am redirected to the failure URL. I have confirmed that there is a user in the MongoDB database and the user supplied password is correct. However, I cannot get past the passport authentication. Can anyone please help me out ?
This is my index.js
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const path = require('path');
const ejsMate = require('ejs-mate');
const loginRoutes = require("./routes/login");
const User = require('./models/users');
const session = require('express-session');
const userRoutes = require('./routes/user');
const passport = require('passport');
const localStrategy = require('passport-local');
sessionConfig = {
name: "session",
secret: 'BetterSecret',
resave: false,
saveUninitialized: true,
cookie: {
httpOnly: true,
expires: Date.now() + 604800000, //Date.NOW + No. of Miliseconds in the week
maxAge: 604800000
}
};
//Connection strings only beyond this line
mongoose.connect('mongodb://localhost:27017/myLoc').then(console.log("DB connected")).catch(error => handleError(error));
app.listen(5500, (req, res, next) => {
console.log("Connected");
});
//app.uses
app.use(express.urlencoded({ extended: true }));
app.use("/", loginRoutes);
app.use("/business", userRoutes);
app.engine('ejs', ejsMate);
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views')); //setting up the views directory
app.use(express.static(path.join(__dirname, 'public'))); //public directory to serve static content
app.use(session(sessionConfig));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
This is the router for the login:
const express = require('express');
const router = express.Router();
const users = require('../controllers/users');
const passport = require('passport');
router.route('/login')
.get(users.renderLoginForm)
.post(passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' }), users.login);
router.route('/register')
.get(users.renderRegisterForm)
.post(users.createNewUser);
module.exports = router;
and for the controller I just have a console.log for now
module.exports.login = (req, res, next) => {
console.log("I am here");
};

req.isAuthenticated() returns false after successRedirect

I know that there are numerous posts already referring to the same problem, however, I couldn't find a solution for my case. Here is the relevant code for the issue :
users.js (route)
The login form is submits a POST request to this route.
var express = require('express');
var router = express.Router();
// Require controllers
var usersController = require('../../controllers/usersController');
/* POST login */
router.post('/login', usersController.loginAccount);
module.exports = router;
usersController.js
The passport authentication is handled here.
req.isAuthenticated() returns false here as well. However, successRedirect is executed, which should mean that the user was successfully authenticated.
'use strict';
var bodyParser = require('body-parser');
var mysql = require('mysql');
var bcrypt = require('bcryptjs');
var Client = require('../models/Client');
var passport = require('passport');
var Sequelize = require('sequelize');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
/* POST - Login */
module.exports.loginAccount = function (req, res, next) {
passport.authenticate('local', {
successRedirect: '../dashboard',
failureRedirect: '/users/login',
failureFlash: true
}) (req, res, next);
console.log("Exactly after authentication: " + req.isAuthenticated());
}
index.js (route)
Here, ensureAuthenticated always returns false
var express = require('express');
var router = express.Router();
// Require controllers
var indexController = require('../../controllers/indexController');
/* GET dashboard page */
router.get('/dashboard', ensureAuthenticated, indexController.dashboardPage);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated())
{console.log("AUTHENTICATED"); return next();}
else{
console.log("NOT AUTHENTICATED");
req.flash('error_msg', 'Please log in to view this resource');
res.redirect('/users/login');
}
}
module.exports = router;
indexController.js
When submitting the login form, this code doesn't get executed, because ensureAuthenticated() is false.
'use strict';
var bodyParser = require('body-parser');
var mysql = require('mysql');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
/* GET - Dashboard page */
module.exports.dashboardPage = function(req, res) {
// console.log(req.user);
// console.log(req.isAuthenticated());
res.render('dashboard');
};
passport.js
const LocalStrategy = require('passport-local').Strategy;
const Sequelize = require('sequelize');
const bcrypt = require('bcryptjs');
// Load User Model
const Client = require('../models/Client');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ usernameField: 'username'}, function(username, password, done) {
// Match User
Client.findOne({ where: {username: username} })
.then(function(user) {
if(!user) {
return done(null, false, { message: 'That username is not registered'});
}
// Match password
bcrypt.compare(password, user.password, function(err, isMatch) {
if(err) throw err;
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect'});
}
});
})
.catch(function(err) { console.log(err) });
})
)
passport.serializeUser(function(user, done) {
console.log('Serializing user');
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log('Deserializing user');
console.log('User ID:', id);
Client.findByPk(id)
.then(function(err, user) {
console.log('User ID:', id);
done(err, user);
});
});
}
All the required middleware is setup in the correct order (express-session -> passport.initialize -> passport.session). cookieParser and express-session are set with the same secret (which is otherwise a problem as other posts suggest).
app.js
var createError = require('http-errors');
var express = require('express');
var expressLayouts = require('express-ejs-layouts');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var mysql = require('mysql');
var flash = require('connect-flash');
var session = require('express-session');
var passport = require('passport');
var bodyParser = require('body-parser');
var cors = require('cors');
// Passport config
require('./config/passport')(passport);
var usersController = require('./controllers/usersController');
var indexRouter = require('./api/routes/index');
var usersRouter = require('./api/routes/users');
var roomsRouter = require('./api/routes/rooms');
var app = express();
app.use(cors());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
// EJS
app.use(expressLayouts);
app.use(express.json());
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser('secret'));
app.use(express.static(path.join(__dirname, 'public')));
// Express Session
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}));
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
In your app.js the routes need to be defined after the passpor middleware is set up.
For Example:
var createError = require('http-errors');
var express = require('express');
var expressLayouts = require('express-ejs-layouts');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var mysql = require('mysql');
var flash = require('connect-flash');
var session = require('express-session');
var passport = require('passport');
var bodyParser = require('body-parser');
var cors = require('cors');
// Passport config
require('./config/passport')(passport);
var usersController = require('./controllers/usersController');
var app = express();
app.use(cors());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
// EJS
app.use(expressLayouts);
app.use(express.json());
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser('secret'));
app.use(express.static(path.join(__dirname, 'public')));
// Express Session
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}));
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
var indexRouter = require('./api/routes/index');
var usersRouter = require('./api/routes/users');
var roomsRouter = require('./api/routes/rooms');
Try doing this and see the output

middleware function error in expressjs

I unable to run node main file in terminal
and I am using handlebar as template engine
getting this weird error
I did npm install all dependencies which is required. but still getting this error.
/home/mohsin/Desktop/mohsin/react/react-web-app/node_modules/express/lib/application.js:210
throw new TypeError('app.use() requires a middleware function')
^
TypeError: app.use() requires a middleware function
this is error screenshot please have look https://i.imgur.com/c6zoaA6.png
My app.js file
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const exphbs = require('express-handlebars');
const expressValidator = require('express-validator');
const flash = require('connect-flash');
const session = require('express-sessions');
const passport = require('passport');
const mongoose = require('mongoose');
// Port env
const port = 3000;
// Route files
const index = require('./routes/index');
const user = require('./routes/user');
// Init App
const app = express();
// View Engine
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
// Static Folder
app.use(express.static(path.join(__dirname, 'public')));
// Body parser middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false}));
// Express Session
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
// Start server
app.use('/', index);
app.use('/user', user);
// Start Server
app.listen(port, () => {
console.log('Server started on port '+port);
});
There is no package named 'express-sessions'
instead use express-session
so its not returning any method. which app.use can call as method.
Here is package

Pass variable to express router

I want to pass my passport variable to my router class but can't seem to find out how to do this.
Server.js:
const session = require('express-session');
const path = require('path');
const passport = require('passport');
const routes = require('./routes')(passport); //pass variable here
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const mongoose = require('mongoose');
const configDB = require('./config/database.js');
const flash = require('connect-flash');
const app = express();
mongoose.connect(configDB.url);
app.use(express.static(path.join(__dirname, '/dist')));
app.use(cookieParser());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(session({
name: 'sessionid',
secret: 'changethis',
resave: false,
saveUninitialized: true,
cookie: {secure: true}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(routes);
app.listen(8080, function () {
console.log('App started on port 8080');
});
/routes/index.ejs: (I want the passport variable here).
const routes = require('express').Router();
const path = require('path');
const api = require('./api');
routes.use('/api', api);
routes.get('/*', function (req, res) {
res.sendFile(path.join(path.dirname(require.main.filename) + '/dist/index.html'));
});
module.exports = routes;
What do I need to do in the index.ejs to get the passport variable?
You need to changes your /routes/index.ejs to export factory function.
const path = require('path');
const api = require('./api');
module.exports = function factory(yourVar) {
const routes = require('express').Router();
routes.use('/api', api);
routes.get('/*', function (req, res) {
res.sendFile(...);
});
return routes;
}

Node.js + express: specify routes

In my understanding, the way to serve views is to do the following:
app.set('view engine', 'ejs'); // or jade or whatever
app.set('views', __dirname + '/views'); // specify where to find the view files e.g. index.ejs
app.get("/", function(req, res) { res.render('index') });
However, when I check the code here https://github.com/jedireza/drywall/ , which is a boilerplate for node user management, I don't see any routes defined in app.js. But it works fine and if I type the url /signup in browser it will render signup.jade.
Which part, or which middleware is doing the magic of routing?
app.js content:
'use strict';
//dependencies
var config = require('./config'),
express = require('express'),
cookieParser = require('cookie-parser'),
bodyParser = require('body-parser'),
session = require('express-session'),
mongoStore = require('connect-mongo')(session),
http = require('http'),
path = require('path'),
passport = require('passport'),
mongoose = require('mongoose'),
helmet = require('helmet'),
csrf = require('csurf');
//create express app
var app = express();
//keep reference to config
app.config = config;
//setup the web server
app.server = http.createServer(app);
//setup mongoose
app.db = mongoose.createConnection(config.mongodb.uri);
app.db.on('error', console.error.bind(console, 'mongoose connection error: '));
app.db.once('open', function () {
//and... we have a data store
});
//config data models
require('./models')(app, mongoose);
//settings
app.disable('x-powered-by');
app.set('port', config.port);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
//middleware
app.use(require('morgan')('dev'));
app.use(require('compression')());
app.use(require('serve-static')(path.join(__dirname, 'public')));
app.use(require('method-override')());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser(config.cryptoKey));
app.use(session({
resave: true,
saveUninitialized: true,
secret: config.cryptoKey,
store: new mongoStore({ url: config.mongodb.uri })
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(csrf({ cookie: { signed: true } }));
helmet(app);
//response locals
app.use(function(req, res, next) {
res.cookie('_csrfToken', req.csrfToken());
res.locals.user = {};
res.locals.user.defaultReturnUrl = req.user && req.user.defaultReturnUrl();
res.locals.user.username = req.user && req.user.username;
next();
});
//global locals
app.locals.projectName = app.config.projectName;
app.locals.copyrightYear = new Date().getFullYear();
app.locals.copyrightName = app.config.companyName;
app.locals.cacheBreaker = 'br34k-01';
//setup passport
require('./passport')(app, passport);
//setup routes
require('./routes')(app, passport);
//custom (friendly) error handler
app.use(require('./views/http/index').http500);
//setup utilities
app.utility = {};
app.utility.sendmail = require('./util/sendmail');
app.utility.slugify = require('./util/slugify');
app.utility.workflow = require('./util/workflow');
//listen up
app.server.listen(app.config.port, function(){
//and... we're live
});
The routes are being added here:
//setup routes
require('./routes')(app, passport);

Resources