I am new to nodejs(v4.5) & express(v4) and i am trying to create login with passport js(local) . i tried a lot but i always get 401 error. I also checked forums but could not find the solution.
Express-session is v1.5.
This is my code:
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var bodyParser = require('body-parser');
var passport = require('passport');
var flash = require('connect-flash');
var base = require('./base');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
require('./config/passport')(passport);
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: 'vidyapathaisalwaysrunning',
resave: false,
saveUninitialized: true
} ));
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash());
app.use(function (req, res, next) {
req.rooturl = req.protocol + '://' + req.get('host') + '/';
next();
});
require('./routes/admin')(app, passport);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
db.js
var mysql = require('mysql');
var sqlConnection = function sqlConnection(sql, values, next) {
if (arguments.length === 2) {
next = values;
values = null;
}
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
port: 3306,
database : 'test'
});
connection.connect(function(err) {
if (err !== null) {
console.log("[MYSQL] Error connecting to mysql:" + err+'\n');
}
});
connection.query(sql, values, function(err) {
connection.end();
if (err) {
throw err;
}
// Execute the callback
next.apply(this, arguments);
});
}
module.exports = sqlConnection;
admin.js
var db = require('../config/db');
module.exports = function(app, passport){
app.get('/admin', function(req, res) {
res.render('login/admin', {
rooturl: req.rooturl,
title: 'Crud'
});
});
app.post('/admin', passport.authenticate('local-login'), function(req, res) {
res.json('5');
});
};
admin.ejs
$('#login').validate({
submitHandler: function(form){
var data = $(form).serialize();
$.ajax({
type:'post',
url: document.url,
//data: new FormData(form),
data: data,
processData: false,
cache: false,
success: function(d){
alert(JSON.stringify(d));
}
});
return false;
}
});
passport.js
var LocalStrategy = require('passport-localapikey').Strategy;
var db = require('./db');
module.exports = function(passport) {
// console.log('5');
passport.serializeUser(function(user, done) {
console.log('4');
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
db("SELECT * FROM user WHERE id = ? ",[id], function(err, rows){
console.log('6');
done(err, rows[0]);
});
});
passport.use('local-login',
new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, username, password, done) {
console.log(username);
db("SELECT * FROM user WHERE email = ? and password = ?",[username, password], function(err, rows){
console.log('2');
if (err)
return done(err);
if (!rows.length) {
return done(null, false, req.flash('loginMessage', 'No user found.'));
}
if(password != rows[0].password){
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
}
return done(null, rows[0]);
});
})
);
}
Related
I've been running through a problem and I can not find out what it is. I am using Express for this.
I have an "addUser" form which has the following Pug form :
form(action='/adduser', method='POST')
and I have try POST method in the app.js that doesn't work :
app.post("/adduser", function (req, res, info, next){
console.log('This does not appear');
});
What I don't understand is why the following login POST method which is just right above the adduser works perfectly :
app.post("/login", passport.authenticate('local', {
// login things
});
NB : At the beginning, the /adduser was in a router and was also returning 404, that's why I tried to move it in app.js .
Feel free to ask any informations that you need.
Anthony.
FULL CODE
app.js:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var escape = require('escape-html');
var stock = require('./routes/stock');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// Variables pour le système d'users
var flash = require('connect-flash');
var crypto = require('crypto');
/* Login script */
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var connection = require('./lib/dbconn');
var sess = require('express-session');
var Store = require('express-session').Store;
var BetterMemoryStore = require(__dirname + '/memory');
var store = new BetterMemoryStore({expires: 60 * 60, debug: true});
app.use(sess({
name: 'StockInfo Sess.',
secret: 'C3ci3stUnSup3rS3cr3t',
store: store,
resave: true,
saveUninitialized: true
}));
//======================================================================================================================
// Configs =============================================================================================================
//======================================================================================================================
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.use('/stock', stock);
//passport Strategy -- the express session middleware before calling passport.session()
passport.use('local', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true //passback entire req to call back
}, function (req, username, password, done) {
if (!username || !password) {
return done(null, false, req.flash('message', 'All fields are required.'));
}
var escapeData = escape(username);
var comboPrenomNom = escapeData.split(".");
var prenom = comboPrenomNom[0].toLowerCase();
var nom = comboPrenomNom[1].toLowerCase();
connection.query("SELECT id, password, salt FROM users WHERE prenom = ? and nom = ?", [prenom, nom], function (err, rows) {
if (err) return done(req.flash('message', err));
if (!rows.length) {
return done(null, false, req.flash('message', 'Invalid username or password.'));
}
if (!(rows[0].password === crypto.createHash('sha256').update(rows[0].salt + escape(password)).digest('hex'))) {
return done(null, false, req.flash('message', 'Invalid username or password.'));
}
req.session.user = rows[0].id;
return done(null, rows[0].id);
});
}
));
passport.serializeUser(function (id, done) {
done(null, id);
});
passport.deserializeUser(function (id, done) {
connection.query("SELECT id, prenom, nom, hasChangedPass, rights FROM users WHERE id = " + id, function (err, rows) {
done(err, rows[0]);
});
});
//======================================================================================================================
// Routes ==============================================================================================================
//======================================================================================================================
app.get('/', function (req, res, next) {
res.redirect('/login');
});
app.get('/login', function (req, res) {
res.render('login/index', {
title: 'LogIn',
message: req.flash('message')
});
});
app.post("/login", passport.authenticate('local', {
successRedirect: '/stock',
failureRedirect: '/login',
failureFlash: true
}), function (req, res, info) {
res.render('login/index', {
'message': req.flash('message')
});
});
app.post("/adduser", function (req, res, info, next) {
if (req.body.prenom && req.body.nom && req.body.password) {
var prenom = escape(req.body.prenom).toLowerCase();
var nom = escape(req.body.nom).toLowerCase();
connection.query("SELECT * FROM users WHERE prenom = ? and nom = ?", [prenom, nom], function (err, rows) {
if (err) {
console.log(err);
}
if (!rows.length) {
var salt = generate_token(32);
var password = escape(req.body.password);
password = crypto.createHash('sha256').update(salt + '' + password).digest('hex');
connection.query("INSERT INTO users (prenom, nom, password, salt) VALUES (?, ?, ?, ?);", [prenom, nom, password, salt], function (err) {
if (err) {
console.log(err);
}
});
}
});
} else {
res.redirect('/stock/fromage');
}
});
app.get('/logout', function (req, res) {
req.session.destroy();
req.logout();
res.redirect('/login');
});
// 404
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error', {title: err.status});
});
function hasRights(req, res, next) {
if (req.user.rights[0] == 1 || req.user.rights[1] == 2 || req.user.rights[2] == 2 || req.user.rights[3] == 2) {
return next();
}
res.redirect('/stock');
}
function isAuthenticated(req, res, next) {
if (req.session.user) {
if (req.user.hasChangedPass) {
return next();
} else {
res.redirect('/stock/initpass');
}
}
res.redirect('/login');
}
module.exports = app;
/login/register.pug
extends ../layout
block content
include ../templates/header
.wrapper
form(action='/adduser', method='POST')
h3 Nouvel utilisateur
div.form-row
div.form-group
input.form-control(type='text', placeholder='Prénom', name='prenom' required)
div.form-row
div.form-group
input.form-control(type='text', placeholder='Nom', name='nom' required)
div.form-row
div.form-group
input.form-control(type='text', placeholder='Mot de Passe', name='password', value= pass required)
div.form-row
div.form-group
button.form-control Créer
div.form-row
div.form-group
p= rights
In your /adduser route you have 4 parameters in the callback function: (req, res, info, next). Remove info and Express will find your route.
With four parameters Express interprets your handler function as an error handler, see more information here: https://expressjs.com/en/guide/error-handling.html. Because of that you get a 404, as the request is passed through the middleware chain into the 404 handler.
When a logged-in user gets to a page through the browser using EJS I'm able to get the function to do what it's supposed to but when I use the API with Ionic using a logged in user with JWT, the async.parallel function doesn't "wait" to do things in order.
Here is my function:
console.log('1');
async.parallel([
function(callback){
buildAlertButtonsArray.getRealTestAlerts(req,function(arrayAlerts) {
console.log('2');
callback(null, arrayAlerts);
});
},
function(callback) {
if(req.decoded) //API
callback('API');
else //EJS
functions.aclSideMenu(req, res, function (acl) {callback(null, acl);}); //aclPermissions sideMenu
}
],function(err, results){
console.log('3');
})
when I login through the browsed on my console.log() is 1, 2, 3 but when I login through the API using JWT I get 1, 3, 2.
Here is my app.js:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
var bluebird = require('bluebird');
//me
var mongoose = require('mongoose');
var db = mongoose.connection;
var cors = require('cors');
var session = require('client-sessions');
var flash = require('express-flash');
//.js file
var routesApi = require('./routes/api');
var routesEjs = require('./routes/ejs');
var routes = require('./routes/index');
//var login = require('./routes/authentication/login');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(cookieParser());
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded({ extended: true })); //was FALSE by default. was TRUE for auth Template
// middleware
app.use(session({
cookieName: 'session',
secret: 'mysecret',
duration: 30 * 60 * 1000,
activeDuration: 30 * 60 * 1000,
httpOnly: true, //doesn't let javascript access cookies ever
secure: true, // only use cookies over https
ephemeral: true // delete this cookie when the browser is closed (nice when people use public computers)
}));
app.use(flash());
app.use(function(req, res, next){
res.locals.success_messages = req.flash('success_messages');
res.locals.error_messages = req.flash('error_messages');
next();
});
// use cors
app.use(cors());
app.use('/public', express.static(path.join(__dirname, 'public')));
app.use('/api', routesApi);
app.use('/', routes);
app.use('/', routesEjs);
//bluebird
mongoose.Promise = require('bluebird');
//connecting to database
mongoose.connect('mongodb://myip:2999/SMECS_database', { useMongoClient: true });
//if we connect successfully or if a connection error occurs
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
// yay!
});
// error handlers
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
Here is my Login function for both EJS using CSRF and API using JWT:
module.exports.postLogin = function(req, res, next) {
if (req.body.pushToken) { // run SMECS API
models.Users.findOne({
email: req.body.email.toLowerCase()
}, function (err, user) {
if (err) throw err;
if (!user) {
res.json({success: false, message: 'Authentication failed. User not found.'});
} else if (user) {
//check if password matches
if (!bcrypt.compareSync(req.body.pin, user.pin)) {
res.json({success: false, message: 'Authentication failed. Wrong password.'});
} else {
// if user is found and password is right
// create a token
var token = jwt.sign({user: user}, config.secret, {
//expiresIn: 1440 // expires in 24 hours
});
user.save(function (err) {
if (err) {
res.json({
success: false,
message: 'contact your system administrator. pushToken not saved'
});
} else {
// return the information including token as JSON
res.json({
success: true,
message: 'Welcome aboard!',
token: token,
userRoleID: user.userRoleID,
userRoleName: user.userRoleName,
userPrivilegeID: user.userPrivilegeID,
userPrivilegeName: user.userPrivilegeName,
firstName: user.firstName,
lastName: user.lastName,
email: user.email
});
}
});
}
}
});
}
else { //run SMECS EJS
models.Users.findOne({email: req.body.email.toLowerCase()}, function (err, user) {
if (!user || user.softDeleted !== null) {
//Parent Self Registration Login
models.ParentSelfRegistration.findOne({email: req.body.email.toLowerCase()}, function (err, parentSelfRegistration) {
if (!parentSelfRegistration) {
res.render('login', {error: "ERROR: Incorrect email or pin.", csrfToken: req.csrfToken()});
} else {
if (req.body.pin == parentSelfRegistration.pin) {
req.session.user = parentSelfRegistration;
res.redirect('/parentsSelfRegistration/registerParentStep1');
} else {
res.render('login', {error: "ERROR: Incorrect email or pin.", csrfToken: req.csrfToken()});
}
}
});
//END OF checks for users in UtilityUsers database
} else {
if (bcrypt.compareSync(req.body.pin, user.pin)) { // if user is found and password is right
req.session.user = user;
res.redirect('/dashboard');
//}
} else {
//res.status(400).send('Current password does not match');
res.render('login', {error: "ERROR: Incorrect email or pin.", csrfToken: req.csrfToken()});
//res.render('login', { error: "ERROR: Incorrect email or pin."});
}
}
});
}
};
Here is my ejs.js file:
//Dependencies
var express = require('express');
var routerEjs = express.Router();
var login = require('./authentication/login');
var auth = require('./authentication/auth');
var chooseAlert = require('./alerts/sendingReceiving/1.chooseAlert');
var login = require('./authentication/login');
var csrf = require('csurf');
routerEjs.use(csrf());
/* GET login page. */
routerEjs.get('/login', login.getLogin, function(req, res) {});
routerEjs.post('/login', login.postLogin, function(req, res) {});
routerEjs.get('/logout', login.getLogout, function(req, res) {});
module.exports = routerEjs;
and my api.js file:
//Dependencies
var express = require('express');
var routerApi = express.Router();
var login = require('./authentication/login');
var auth = require('./authentication/auth');
var chooseAlert = require('./alerts/sendingReceiving/1.chooseAlert');
routerApi.post('/login', login.postLogin, function(req, res) {});
routerApi.get('/chooseGroup', auth.auth, chooseAlert.showGroups, function(req, res) {});
routerApi.get('/alerts/sending/chooseAlert', auth.auth, chooseAlert.showAlerts, function(req, res) {});
/* Update pushToken ------------------------------------*/
routerApi.post('/updatePushToken', auth.auth, auth.pin, function(req, res) {});
module.exports = routerApi;
I figured out my problem. I was missing a NULL on my callback...
console.log('1');
async.parallel([
function(callback){
buildAlertButtonsArray.getRealTestAlerts(req,function(arrayAlerts) {
console.log('2');
callback(null, arrayAlerts);
});
},
function(callback) {
if(req.decoded) //API
callback(NULL, 'API');
else //EJS
functions.aclSideMenu(req, res, function (acl) {callback(null, acl);}); //aclPermissions sideMenu
}
],function(err, results){
console.log('3');
})
I two questions about render view,
Why It does not work? If i put res.render into if(error), it not render new site, but is still on current page.
And second question is, if I in ejs template view, I put <%= errors %> to display errors, and its does it work, is shown Error File Not Found
router.post('/create', function (req, res, next) {
var newUser = {
username: req.body.username,
password: req.body.password
}
req.checkBody('username', 'Login is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
var errors = req.validationErrors();
if(errors){
console.log(errors)
res.render('index',{
errors:errors
// console.log(errors)
// res.send(errors);
});
} else {
bcrypt.hash(newUser.password, saltRounds, function (err, hash) {
if (err) {
console.log(err)
} else {
newUser.password = hash;
var user = new User(newUser);
user.save()
.then(function (User) {
res.send(User);
})
}
});
req.flash('success_msg', 'You are registered and can now login');
//res.redirect('/');
}
});
on console.log(errors) is
[ { param: 'username', msg: 'Login is required', value: undefined },
{ param: 'password',
msg: 'Password is required',
value: undefined } ]
The express render method can also return errors. Use the callback to determine whether this is happening and add a return to stop logic after the else statement from occurring.
var errors = req.validationErrors();
if(errors){
return res.render('index', { errors: errors }, function (err, html) {
if (err) console.error(err);
res.send(html);
});
}
bcrypt.hash(newUser.password, saltRounds, function (err, hash) {
if (err) {
console.log(err)
} else {
newUser.password = hash;
var user = new User(newUser);
user.save()
.then(function (User) {
res.send(User);
})
}
});
req.flash('success_msg', 'You are registered and can now login');
return res.redirect('/');
APP.js
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var favicon = require('serve-favicon');
var logger = require('morgan');
var expressValidator = require('express-validator');
var flash = require('connect-flash');
var session = require('express-session');
var passport = require('passport');
var LocalStategy = require('passport-local').Strategy;
var indexPage = require('./routes/index/index');
var productPage = require('./routes/product/product');
var userPage = require('./routes/user/user');
var categoryPage = require('./routes/category/category');
var filenotfound = require('./routes/error/error');
var mongoose = require('mongoose');
var Product = require('./model/product.model');
var Category = require('./model/category.model');
var User = require('./model/user.model');
var app = express();
mongoose.connect('mongodb://localhost/products', function (error) {
if (error) {
console.log('blad w polaczeniu')
} else {
console.log('connected');
//=========================CONNNNNNECTTTTTTEEEEEEDDDDDDDDDDDDDDDD======================//
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use('/assets', express.static('public'));
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: 'dadasdasdaxsax',
resave: true,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
// Express Validator
app.use(expressValidator({
errorFormatter: function (param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while (namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param: formParam,
msg: msg,
value: value
};
}
}));
// Connect Flash
app.use(flash());
// Global Vars
app.use(function (req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
res.locals.user = req.user || null;
next();
});
app.use('/', indexPage);
app.use('/product', ensureAuthenticated, productPage);
app.use('/user', userPage);
app.use('/category', ensureAuthenticated, categoryPage);
app.use('/error', filenotfound);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
//req.flash('error_msg','You are not logged in');
res.redirect('/');
}
}
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
//=========================CONNNNNNECTTTTTTEEEEEEDDDDDDDDDDDDDDDD======================//
}
});
module.exports = app;
I saw a couple of post with similar to mine but I still getting the same error
here is my user schema
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
var userSchema = mongoose.Schema({
local: {
email: String,
password: String,
},
});
userSchema.methods.generateHash = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};
userSchema.methods.validPassword = function(password) {
return bcrypt.compareSync(password, this.local.password);
};
module.exports = mongoose.model('User', userSchema);
my routes
var express = require('express');
var passport = require('passport');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/login', function(req, res, next) {
res.render('login.ejs', { message: req.flash('loginMessage') });
});
router.get('/signup', function(req, res) {
res.render('signup.ejs', { message: req.flash('loginMessage') });
});
router.get('/profile', isLoggedIn, function(req, res) {
res.render('profile.ejs', { user: req.user });
});
router.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
router.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/profile',
failureRedirect: '/signup',
failureFlash: true,
}));
router.post('/login', passport.authenticate('local-login', {
successRedirect: '/profile',
failureRedirect: '/login',
failureFlash: true,
}));
module.exports = router;
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
my app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongoose = require('mongoose');
var flash = require('connect-flash');
var session = require('express-session');
var routes = require('./routes/index');
var users = require('./routes/users');
var configDB = require('./config/database.js');
mongoose.connect(configDB.url);
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({ secret: 'shhsecret' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
require('./config/passport')(passport);
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
And here is my passport.js Im using local passport
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
},
function(req, email, password, done) {
process.nextTick(function() {
User.findOne({ 'local.email': email }, function(err, user) {
if (err)
return done(err);
if (user) {
return done(null, false, req.flash('signupMessage', 'That email is already in use.'));
} else {
var newUser = new User();
newUser.local.email = email;
newUser.local.password = newUser.generateHash(password);
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
});
}));
passport.use('local-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
},
function(req, email, password, done) {
User.findOne({ 'local.email': email }, function(err, user) {
if (err)
return done(err);
if (!user)
return done(null, false, req.flash('loginMessage', 'No user found.'));
if (!user.validPassword(password))
return done(null, false, req.flash('loginMessage', 'Wrong password.'));
return done(null, user);
});
}));
};
passport works it save the user to the database
expressauth 5 > db.users.find()
{ "_id" : ObjectId("586cc8b3ea780c071bbe2469"), "local" : { "password" : "$2a$08$vANw7GJIk8RUVEpJWnwSpOVQ77RuHCjbXiGoQVl.Fx/thhbMkEVWu", "email" : "david#david.com" }, "__v" : 0 }
expressauth 6 >
Cast to ObjectId failed for value “586cc8b3ea780c071bbe2469” at path “_id” for model “User”
I have built a couple apps that use passport oauth the exact same way that I have displayed above. So I dont know why Im getting this error.
Any suggestions?
I had the same problem with mongoose version > 4.7.2
Problem is about bson package.
I solved it with installing an older version of mongoose.
npm install mongoose#4.7.2
or you can change package.json to use exact version 4.7.2 "mongoose": "4.7.2"
You can update to newer versions after the problem is solved. You can track it on here.
The error exists in your serializeUser function in passport.
You need to use user._id instead of user.id.
since there is no field as id in your UserSchema, user.id will beundefined, and while deserializing the user, undefined is not typeOf ObjectId, thus it is throwing above error.
Try this:
passport.serializeUser(function(user, done) {
done(null, user._id);
});
Update:
Do this in your deserializeUser:
cast the upcoming id to ObjectId, just to be sure, and then use that ID to query the User.
var userId = mongoose.Schema.Types.ObjectId(id);
User.findById(userId , function(err, user) {
done(err, user);
});
Dont forget to include mongoose in the same file.
var mongoose=require('mongoose');
Hopefully this will help you.
This is due to latest version of mongoose, you have to use findOneAndRemove instead of FindByIdAndRemove.
That is cast objectId problem.
I am using nodejs, passportjs, jwtoken and mongoose to develop an application. I am facing some critical situation and stuck since 2 days.
I have used passport js for server side authentication and jwtoken for persistent login. It works very well ,with regular situation. But I have faced an issue before 3 days ago that when I restart server passport js fails to maintain session or expire nodejs user session. I don't know how to revalidate and recreate new passport session in nodejs.
I have tried a lot but failed to recreate. I found this issue when I tried to restart server and from web application any request sent to server. When I tried to access req.user to get user data from session it throws me req.user is undefined.
I even tried to use connect-mongo to store session but it throws an error -
"Error: failed to deserialize user out of session".
I don't know how to deal with situation. Provide me guidelines to resolve this issue.
Please refer below source code.
config.js
var express = require("express");
var http = require("http");
var path = require("path");
var bodyParser = require("body-parser");
var cookieParser = require("cookie-parser");
var expressSession = require("express-session");
var methodOverride = require("method-override");
var morgan = require("morgan");
var passport = require("passport");
var randToken = require('rand-token');
var jwt = require("jsonwebtoken");
var mongoose = require("mongoose");
var app = express();
var useragent = require('express-useragent');
app.use(useragent.express());
require("./utils")(express, app, path);
require("./db");
app.set("port", process.env.PORT || 2000);
app.set("env", "development");
if (app.get("env") === 'production') {
process.env['RECAPTCHA_PRIVATE_KEY'] = **** ;
process.env['JWT_PRIVATE_KEY'] = **** ;
process.env['COOKIE_PRIVATE_KEY'] = **** ;
process.env['JWT_TIME_OUT'] = 60 * 60 * 24 * 30 * 1000; // 30 days
process.env['SECURE_COOKIES'] = true;
} else if (app.get('env') === 'staging') {
process.env['RECAPTCHA_PRIVATE_KEY'] = **** ;
process.env['JWT_PRIVATE_KEY'] = **** ;
process.env['COOKIE_PRIVATE_KEY'] = **** ;
process.env['JWT_TIME_OUT'] = 60 * 60 * 24 * 30 * 1000; // 30 days
process.env['SECURE_COOKIES'] = false;
} else if (app.get('env') === 'development') {
process.env['RECAPTCHA_PRIVATE_KEY'] = **** ;
process.env['JWT_PRIVATE_KEY'] = **** ;
process.env['COOKIE_PRIVATE_KEY'] = **** ;
process.env['JWT_TIME_OUT'] = 60 * 60 * 24 * 30 * 1000; // 30 days
process.env['SECURE_COOKIES'] = false;
}
app.enable('trust proxy');
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(expressSession({
secret: process.env.COOKIE_PRIVATE_KEY,
name: 'hz-app',
proxy: true,
resave: true,
saveUninitialized: true,
httponly: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(methodOverride('X-HTTP-Method-Override'));
var router = express.Router();
var expressJWT = require("express-jwt");
var allowAccess = expressJWT({
secret: process.env.JWT_PRIVATE_KEY,
userProperty: 'payload'
}).unless({
path: [
'/api/user/register',
'/api/user/useractivation',
'/api/user/authenticate',
'/api/user/checkEmail',
'/api/user/checkNickName',
'/api/user/resetPassword',
'/api/user/addip',
'/api/user/forgetPasswordRequest',
'/api/user/logout',
'/api/cms/getCms',
'/adminapi/admin/authnticate',
'/adminapi/admin/logout',
'/adminapi/common/getLanguageList',
'/api/common/getCurrencyList',
'/adminapi/common/getUserType',
'/api/newsSubscriber/create',
// '/api/newsSubcrib/create',
// '/adminapi/admin/userList',
// '/adminapi/admin/getUserType',
// '/adminapi/admin/userCreate',
// '/adminapi/admin/userEdit',
]
});
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, content-type, Authorization');
next();
});
app.all(["/api/*", "/adminapi/*"], allowAccess, function(req, res, next) {
if (req.user) {
console.log("log in authorize obj for check");
console.log(JSON.stringify(req.user));
} else {
console.log("not authenticated (not log in)");
//res.clearCookie('hz-token');
//res.clearCookie('hz-token-admin');
}
var reqPath = req.path.split("/");
console.log('../app/data/routes/' + reqPath[2]);
app.use(require('../app/data/routes/' + reqPath[2]));
next();
});
app.get("/", function(req, res) {
//app.use(function (req, res) {
res.sendFile(basePath + "app/client/views/index.html");
});
app.get("/admin", function(req, res) {
res.sendFile(basePath + "app/admin/views/index.html");
});
//Development error handler will print stacktrace
if (app.get('env') === "development") {
router.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
router.use(function(err, req, res, next) {
res.status(err.status || 500);
});
http.createServer(app).listen(app.get('port'), function() {
console.log('Epsilon is listening on port ' + app.get('port'));
});
exports = module.exports = app;
user.js
var express = require('express');
var router = express.Router();
var Helper = require("../components/helper");
var bcrypt = require("bcryptjs");
var moment = require("moment");
var User = require('../models/user');
var passport = require("passport");
var localStrategy = require("passport-local"),
Startegy;
router
.route('/api/user/authenticate')
.post(
function (req, res, next) {
console.log(">> authentication process initiated");
passport.authenticate('user-local', function (err, user, info) {
if (err) {
return res.status(401).json({
status: 0,
code: 401,
type: "error",
message: err
});
}
if (!user) {
console.log("not user:");
console.log(user);
return res.status(401).json({
status: 0,
code: 401,
type: "error",
message: info
});
}
req.login(user, {}, function (err) {
if (err) {
return res.status(500).json({
status: 0,
code: 500,
type: "other",
err: 'could not login user'
});
}
NextProcessForGenerateWebToken();
var NextProcessForGenerateWebToken = function () {
if (err) {
return next(err);
}
var _res = user.generateJWT(user);
res.cookie('hz-token', _res, {maxAge: process.env.JWT_TIME_OUT, httpOnly: false});
res.status(200).json({
status: 1,
type: "success",
message: 'login successful',
res: {
link: user.link_id,
nick_name: user.nick_name
}
});
};
});
})(req, res, next);
});
/**
* Serialize user for passport authentication
*/
passport.serializeUser(function (user, done) {
console.log("serialize:>>"+user.id);
console.log(user);
done(null, user.id);
});
/**
* Deserialize user for passport authentication
*/
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
console.log("deserialize:>>"+user.id);
done(err, user);
});
});
/**
* Passport local authentication policy to validate email/username and passport
*/
passport.use('user-local', new localStrategy({
usernameField: 'txtSigninEmail',
passwordField: 'txtSigninPassword'
},
function (username, password, done) {
User.findOne({$or: [{email: username}, {nick_name: new RegExp('^' + username + '$', "i")}], user_type: 3, is_active: 1, is_close: 0}, function (err, user) {
if (!user) {
return done(null, false, {message: 'Incorrect username.'});
}
user.comparePassword(password, function (err, isMatch) {
if (err)
throw err;
if (!isMatch) {
return done(null, false, {message: 'Incorrect password.'});
}
return done(null, user);
});
});
}
));
module.exports = router;