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");
};
Related
I'm using passport-local for authentication. When starting from login page I do redirect where I should if usr/pwd is correct and redirect back to login when it's not, but if add the authentication requirement to a page I'm always getting redirected to the login page.
app.js
var express = require('express');
var passport = require('passport');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var authRouter = require('./routes/auth');
var listsRouter = require('./routes/lists');
var app = express();
require('./boot/auth')();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.authenticate('session'));
app.use('/', indexRouter);
app.use('/', authRouter);
app.use('/lists', listsRouter);
module.exports = app;
boot/auth.js
var passport = require('passport');
var Strategy = require('passport-local');
module.exports = function () {
passport.use(new Strategy(function (username, password, cb) {
if (checkUsrPwd()) {
var user = {
id: '1',
username: 'my_user',
displayName: 'user name'
};
return cb(null, user);
} else {
return cb(null, false, {
message: 'Incorrect username or password.'
});
}
}));
passport.serializeUser(function (user, cb) {
process.nextTick(function () {
cb(null, {
id: user.id,
username: user.username
});
});
});
passport.deserializeUser(function (user, cb) {
process.nextTick(function () {
return cb(null, user);
});
});
};
routes/lists.js
const express = require('express');
const ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
const router = express.Router();
router.get("/list", ensureLoggedIn('/'), (req, res) => {
[...]
res.contentType = 'application/json';
res.render('list', {
userData: items
});
};
});
});
What did I miss?
I was missisng a line in my app.js
app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
After adding that everything is working fine.
I am trying to run a nodejs app. The problem that I have however is every time I try to run the app, it throws an error as stated in the title: misconfigured csrf.
Here is my code:
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
const csrf = require('csurf');
const flash = require('connect-flash');
const errorController = require('./controllers/error');
const User = require('./models/user');
const MONGODB_PASS = 'PASSWORD_HERE';
const MONGODB_URI = `mongodb+srv://USER_HERE:${MONGODB_PASS}#DB_HOST_HERE/shop?retryWrites=true&w=majority`;
const app = express();
const store = new MongoDBStore({
uri: MONGODB_URI,
collection: 'sessions'
});
const csrfProtection = csrf({cookie: true});
app.set('view engine', 'ejs');
app.set('views', 'views');
const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
const authRoutes = require('./routes/auth');
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: 'my secret',
resave: false,
saveUninitialized: false,
store
}));
app.use(csrfProtection);
app.use(flash());
app.use((req, res, next) => {
if (!req.session.user) return next();
User.findById(req.session.user._id).then(user => {
req.user = user;
next();
}).catch(err => {throw err});
});
app.use((req, res, next) => {
res.locals.isAuthenticated = req.session.isLoggedIn;
req.locals.csrfToken = req.csrfToken();
next();
});
app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.use(authRoutes);
app.use(errorController.get404);
mongoose.connect(MONGODB_URI)
.then(result => app.listen(3000)).catch(err => { throw err });
I expect the app to run successfully but instead, it throws an error saying: misconfigured csrf. What am I doing wrong?
Note: I seriously don't know what to write anymore and SO keeps complaining that i need to add some more details. I believe i've provided enough explanation with the description, the title, and the code.
You are using the cookie option:
const csrfProtection = csrf({cookie: true});
It requires the cookie-parser package as documented here: If you are setting the "cookie" option to a non-false value, then you must use cookie-parser before this module.
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
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());
I'm trying to build a login system using express and passport.
As far as I know, I can use the req.user to access user id and correctly store their actions and req.isAuthenticated() would be true if Passport is working properly, however it isn't working.
For some reason, req.user is always undefined and req.isAuthenticated() is always false.
This is my app.js ->
const express = require('express');
const http = require('http');
const session = require('express-session');
const bodyParser = require('body-parser');
const passport = require('passport');
const route = require('./controllers/core'); **// CORE.JS**
const app = express();
app.set('view engine', 'ejs');
app.use('/css', express.static('css'));
app.use('/js', express.static('js'));
app.use('/themify', express.static('themify'));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
//cookie: { secure: true }
}));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(passport.initialize());
app.use(passport.session());
app.use(route);
//core(app);
app.listen(3000);
And this is my core.js
const router = require('express').Router();
const passport = require('passport');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'pharmate',
dateStrings: 'date'
});
const urlencodedParser = bodyParser.urlencoded({ extended: false });
router.get('/index', function(req,res){
console.log(req.user);
});
router.post('/index', urlencodedParser, function(req,res){
var email = req.body.email;
var pass = req.body.password;
connection.query("SELECT `Pharmacy_ID`, `Email`, `Password` FROM `pharmacy` WHERE Email = ? AND Password = ?", [email, pass], function (error, results, fields) {
if (error) res.send(error);//throw error;
else{
if(results.length>0){
req.login(results[0], function(err){
res.redirect('index');
});
}
else{
res.redirect('login');
}
}
});
});
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
done(null, user);
});
module.exports = router;
Any help would be appreciated. Thanks in advance.
You should handle the authentication like:
app.post('/login',
passport.authenticate('local', {
successRedirect: '/secret',
failureRedirect: '/login',
})
);
Did you setup the passport local strategy ?