I have my login system up on localhost and register page is working but not the login page. It keep showing me invalid password.
btw i am using mongodb as my database.
On my mongodb, i'm able to view those data that have been stored on the mongo shell.
I appreciate those who are able to review those codes. Thanks!!
Image:
showing invalid password image
here are my code:
app.js
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var exphbs = require('express-handlebars');
var expressValidator = require('express-validator');
var flash = require('connect-flash');
var session = require('express-session');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongo = require('mongodb');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/loginapp');
var db = mongoose.connection;
var routes = require('./routes/index');
var users = require('./routes/users');
//Init App
var app = express();
//View Engine
app.set('views', path.join(__dirname, 'views')); //handle view
app.engine('handlebars', exphbs({defaultLayout:'layout'})); //set default view to layout
app.set('view engine', 'handlebars'); //set view engine to handlebars
//BodyParser Middleware (Configuration)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
//Set static folder (public folder.. stylesheet,images)
app.use(express.static(path.join(__dirname, 'public')));
//Express Session (Middleware for express session)
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
//Passport init
app.use(passport.initialize());
app.use(passport.session());
//Express Validator (Middleware for 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 (global func)
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();
});
//Middleware for route files
app.use('/', routes); //map to routes index files
app.use('/users', users);
//Set Port (start the server)
app.set('port', (process.env.PORT || 3000));
app.listen(app.get('port'), function(){
console.log('Sever started on port '+app.get('port'));
});
routes/users
var express = require('express');
var router = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
// Register
router.get('/register', function(req, res){
res.render('register');
});
// Login
router.get('/login', function(req, res){
res.render('login');
});
// Register User
router.post('/register', function(req, res){
//Get all the stuff into variable
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
//Validation
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
req.checkBody('username', 'Username is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('password2', 'Passwords do not match').equals(req.body.password);
var errors = req.validationErrors();
if(errors){
res.render('register',{
errors:errors
});
} else {
var newUser = new User({
name: name,
email: email,
username: username,
password: password
});
User.createUser(newUser, function(err, user){
if(err) throw err;
console.log(user);
});
req.flash('success_msg', 'You are registed and can now login');
res.redirect('/users/login');
}
});
passport.use(new LocalStrategy(
function(username, password, done) {
User.getUserByUsername(username, function(err, user){
if(err) throw err;
if(!user){
return done(null, false, {message: 'Unknown User'});
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err;
if(isMatch){
return done(null, user);
} else {
return done(null, false, {message: 'Invalid password'});
}
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
router.post('/login',
passport.authenticate('local', {successRedirect:'/', failureRedirect:'/users/login',failureFlash: true}),
function(req, res) {
res.redirect('/');
});
router.get('/logout', function(req, res){
req.logout();
req.flash('success_msg', 'You are logged out');
res.redirect('/users/login');
});
module.exports = router;
models/user
var mongoose = require('mongoose');
//hash password
var bcrypt = require('bcryptjs');
//User schema
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true
},
password: {
type: String
},
email: {
type: String
},
name: {
type: String
}
});
//Variable that can access outside this file
var User = module.exports = mongoose.model('User', UserSchema);
//User function
module.exports.createUser = function(newUser, callback) {
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash("newUser.password", salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
}
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
if(err) throw err;
callback(null, isMatch);
});
}
You have a mistake here
module.exports.createUser = function(newUser, callback) {
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash("newUser.password", salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
}
It must be
bcrypt.hash(newUser.password, salt, function(err, hash) {
//__________^______________^ removed quotes
newUser.password = hash;
newUser.save(callback);
});
For that reason when user registers, it's password was set "newUser.password", but not actually user's password
Related
I am trying to implement a simple user login and signup page for my application.
The signup page works and everything is getting stored in mongodb correctly. However, when I try to login it it does not seem to work. It is supposed to redirect to my root page but it will not do that. It always redirect back to /users/login
I've been going through a tutorial online so I do not understand why this isn't working. Here are the relevant files files.
user.js file
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
let User = require('../models/user');
// Load register form
router.get('/register', function(req, res) {
res.render('register', {
title : 'Register',
errors : req.flash('success')
});
});
// Submit register form
router.post('/register', function(req, res) {
// Get the fields from the form
const firstname = req.body.firstname;
const lastname = req.body.lastname;
const email = req.body.email;
const pass = req.body.pass;
const pass2 = req.body.pass2;
// Verify body is not empty.
req.checkBody('firstname', 'First name is required').notEmpty();
req.checkBody('lastname', 'Last name is required').notEmpty();
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
req.checkBody('pass', 'Password is required').notEmpty();
req.checkBody('pass2', 'Passwords do not match.').equals(req.body.pass);
// Check for errors
let errors = req.validationErrors();
if (errors) {
res.render('register', {
errors:errors
});
} else {
// Create new user object
let newUser = new User({
firstname:firstname,
lastname:lastname,
email:email,
pass:pass
});
// Hash the password for security.
bcrypt.genSalt(10, function(err, salt){
bcrypt.hash(newUser.pass, salt, function(err, hash) {
if (err) {
console.log(err);
}
newUser.pass = hash;
newUser.save(function(err) {
if (err) {
console.log(err);
return;
} else {
console.log("Successful creation.")
req.flash('success', 'Account creation successful!');
res.redirect('/users/login');
}
});
});
})
}
});
// Load login form
router.get('/login', function(req, res){
res.render('login');
});
// Submit login form
router.post('/login', function(req, res, next) {
passport.authenticate('local', {
successRedirect: '..',
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
});
module.exports = router;
passport.js file
const LocalStrategy = require('passport-local').Strategy;
const passport = require('passport');
const User = require('../models/user');
const config = require('../config/database');
const bcrypt = require('bcryptjs');
// User Authentication
module.exports = function(passport){
console.log("Made it intro str");
passport.use(new LocalStrategy(function(email, pass, done){
// Match username
let query = {email:email};
User.findOne(query, function(error, user){
if (error){
console.log("error");
return done(error);
}
if (!user) {
console.log("No user found");
return done(null, false, {message: 'No user found.'});
}
bcrypt.compare(pass, user.pass, function(error, isMatch) {
if (error) {
console.log("error2");
return done(error);
}
if (isMatch) {
console.log("Matching password");
return done(null, user);
} else {
console.log("Wrong password");
return done(null, false, {message: 'Invalid password.'});
}
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
}
App.js
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const logger = require('morgan');
const session = require('express-session');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const expressValidator = require('express-validator');
const config = require('./config/database');
const flash = require('connect-flash');
const passport = require('passport');
/* Connect to Database */
mongoose.connect(config.database, { useNewUrlParser: true });
let db = mongoose.connection;
// Check connection.
db.once('open', function(){
console.log('Connected to MongoDB.');
})
// Check DB error.
db.on('error', function(error){
console.log(error);
});
/* Initialize app */
var app = express();
/* Bring in models for database */
let User = require('./models/user');
// Body Parser Middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Load the view engines
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// Set public folder
app.use(express.static(path.join(__dirname, 'public')));
app.use(expressValidator());
// Keep users session
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}));
app.use(require('connect-flash')());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
// Express Validator Middleware
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
};
}
}));
// Passport config
require('./config/passport')(passport);
app.use(passport.initialize());
app.use(passport.session());
// Load homepage
app.get('/', function(req, res) {
res.render('index', {
title: 'Index',
})
})
// Define routes
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/user');
app.use('/', indexRouter);
app.use('/users', usersRouter)
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// 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');
});
;
module.exports = app;
I believe the issue is in your passport.js file... By default, LocalStrategy expects to find credentials in parameters named username and password. You need to change that... something like so:
const localOptions = { usernameField: 'email', passwordField: 'pass' };
passport.use(new LocalStrategy(localOptions, function (email, pass, done) {
// Match username
let query = { email: email };
User.findOne(query, function (error, user) {
// etc etc...
});
}));
Link to the docs (at the bottom of the page...): http://www.passportjs.org/docs/username-password/
I'm a beginner in Angular 5 and I'm currently working on an app. So in login module, the passport local strategy is not working and passport.authenticate function is not working, and I can't seem to find the problem in my code.
Now I am not sure what is wrong because there is no error on the console and the return is null every time. That's why I'm copy pasting a lot of code.
Code is attached below.
Server.js file
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const cors = require('cors');
const app = express();
const cookieParser = require('cookie-parser');
const exphbs = require('express-handlebars');
const expressValidator = require('express-validator');
const flash = require('connect-flash');
const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
// API file for interacting with MongoDB
const api = require('./routes/api');
const auth = require('./routes/auth_companies');
require('./models/passport');
// Parsers/middlewares
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(cookieParser());
app.use(flash());
// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));
app.use(express.static('public'));
// API location
app.use('/api', api);
app.use('/auth', auth);
// Express Session
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
// Passport init
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();
});
// Send all other requests to the Angular app
//app.get('*', (req, res) => {
// res.sendFile(path.join(__dirname, 'dist/index.html'));
//});
// start the server
//app.listen(app.get('port'), () => {
// console.log('server on port 3000');
//});
//Set Port
const port = process.env.PORT || '3000';
app.set('port', port);
const server = http.createServer(app);
console.log(port);
server.listen(port, () => console.log(Running on localhost:${port}));
Passport.js file
const express = require('express');
const router = express.Router();
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require ('./reg_company');
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
passport.use( new LocalStrategy(
function(email, password, done) {
console.log('9900---------------------------------', email)
User.getUserByEmail(email, function(err, user){
if(err) throw err;
if(!user){
return done(null, false, {message: 'Unknown User'});
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err;
if(isMatch){
return done(null, user);
} else {
return done(null, false, {message: 'Invalid password'});
}
});
});
}));
passport.use('local.signup' , new LocalStrategy ({
passReqToCallback : true ,
emailfield:'email',
passwordfield:'password'
}, function(req, email, password, done){
User.findOne({'email':email}, function(err, user){
if (err)
{
return done(err);
}
if (user)
{
return done (null, false);
}
const newCompany=new User();
newCompany.email = req.body.email;
newCompany.password = req.body.passport;
User.createUser(newCompany, function(err, user){
if(err) throw err;
console.log(user);
return done(null, user);
});
})
}) )
Mongo File
const mongoose = require('mongoose');
const uri='mongodb://localhost/tourhubdb';
mongoose.connect(uri);
const db=mongoose.connection;
const bcrypt = require('bcryptjs');
//tourist Schema
let company_reg_schema = mongoose.Schema({
email:{
type:String,
require:true
},
password:
{
type:String,
require:true
}
});
let User = module.exports = mongoose.model('companies',company_reg_schema);
module.exports.createUser = function(newUser, callback){
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(newUser.password, salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.getUserByEmail = function(email, callback){
var query = {email: email};
User.findOne(query, callback);
}
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
if(err) throw err;
callback(null, isMatch);
});
}
Routes file
const express = require("express");
const router = express.Router();
router.post('/login',function (req,res,next){
passport.authenticate('local-login', function (err ,user ,info){
})(req ,res ,next);
});
module.exports = router;
Just my two cents here...wherever you're returning done(null....) under
passport.use(), you could replace the null value with different errors for the different done() calls and see which one invokes and why.
I'm using app.use(express.static(path.join(__dirname,'public'))); to show login page before showing index.html in Node.js.
However, it doesn't show login page before index.html...
I tried to use app.get('/', function (req,res) {res.redirect('/login');}); but it doesn't even go through that app.get and doesn't redirect when it connects to localhost:4000...
my directory setup is shown below
myapp
node_modules
public
images
javascripts
js
stylesheets
index.html
routes
views
login
login.ejs
users
new.ejs
index.jade
layout.jade
app.js
package.json
Also, I want to hold index.html in public folder and just want to display login page before that..
Is there any ways to show that??
Here is my whole code in app.js
var io = require('socket.io');
var express = require('express');
var app = express();
var redis = require('redis');
var sys = require('util');
var fs = require('fs');
//Added for connecting login session
var http = require('http');
var server = http.createServer(app);
var path = require('path');
var mongoose = require('mongoose');
var passport = require('passport');
var session = require('express-session');
var flash = require('connect-flash');
var async = require('async');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
//connecting database
mongoose.connect("my mongoDB private address");
var db = mongoose.connection;
db.once("open",function () {
console.log("DB connected!");
});
db.on("error",function (err) {
console.log("DB ERROR :", err);
});
var bcrypt = require("bcrypt-nodejs");
var userSchema = mongoose.Schema({
email: {type:String, required:true, unique:true},
password: {type:String, required:true},
createdAt: {type:Date, default:Date.now}
});
userSchema.pre("save", function (next){
var user = this;
if(!user.isModified("password")){
return next();
} else {
user.password = bcrypt.hashSync(user.password);
return next();
}
});
userSchema.methods.authenticate = function (password) {
var user = this;
return bcrypt.compareSync(password,user.password);
};
var User = mongoose.model('user',userSchema);
io = io.listen(server);
app.set("view engine", 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
//setting middleware for login
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(methodOverride("_method"));
app.use(flash());
app.use(session({secret:'MySecret', resave: true, saveUninitialized: true}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
var LocalStrategy = require('passport-local').Strategy;
passport.use('local-login',
new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
User.findOne({ 'email' : email }, function(err, user) {
if (err) return done(err);
if (!user){
req.flash("email", req.body.email);
return done(null, false, req.flash('loginError', 'No user found.'));
}
if (!user.authenticate(password)){
req.flash("email", req.body.email);
return done(null, false, req.flash('loginError', 'Password does not Match.'));
}
return done(null, user);
});
}
)
);
//set home routes
//var data_1 = {email:''};
app.get('/', function (req,res) {
res.redirect('/login');
//req.url = '/login';
//next();
});
app.get('/login', function (req,res) {
res.render('login/login',{email:req.flash("email")[0], loginError:req.flash('loginError')});
});
app.post('/login', function(req, res, next) {
passport.authenticate('local-login', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
return res.redirect('/?channel='+ req.body.email);
})(req, res, next);
});
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/login');
});
// set user routes
app.get('/users/new', function(req,res){
res.render('users/new', {
formData: req.flash('formData')[0],
emailError: req.flash('emailError')[0],
passwordError: req.flash('passwordError')[0]
}
);
}); // new
app.post('/users', checkUserRegValidation, function(req,res,next){
User.create(req.body.user, function (err,user) {
if(err) return res.json({success:false, message:err});
res.redirect('/login');
});
}); // create
//functions
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()){
return next();
}else{
res.redirect('/login');
}
res.redirect('/');
}
function checkUserRegValidation(req, res, next) {
var isValid = true;
async.waterfall(
[function(callback) {
User.findOne({email: req.body.user.email, _id: {$ne: mongoose.Types.ObjectId(req.params.id)}},
function(err,user){
if(user){
isValid = false;
req.flash("emailError","- This email is already resistered.");
}
callback(null, isValid);
}
);
}], function(err, isValid) {
if(err) return res.json({success:"false", message:err});
if(isValid){
return next();
} else {
req.flash("formData",req.body.user);
res.redirect("back");
}
}
);
}
function handler(req,res){
console.log(req);
fs.readFile(__dirname + '/public/index.html', function(err,data){
if(err){
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
console.log("Listening on port 3000");
res.end(data);
});
fs.readFile(__dirname + '/public/style.css', function(err,data){
if(err){
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
console.log("Listening on port 3000");
res.end(data);
});
}
io.sockets.addListener('connection', function(socket){
console.log("connceted : " + socket.id);
var subscriber = redis.createClient(6379, 'localhost');
subscriber.psubscribe("*");
subscriber.on("pmessage", function(pattern, channel, message) {
//console.log(message);
socket.emit(channel, message);
});
socket.on('disconnect', function () {
console.log("disconnceted : " + socket.id);
subscriber.quit();
});
socket.on('close', function() {
console.log("close");
subscriber.quit();
});
});
app.listen(4000, function(){
console.log('Server On!!!');
});
Should I use another express to display login page? or what should I do here?
I'm actually newbie in node.js.
Can anybody please help me out here??
Thank you..
EDIT: My whole code for app.js
var express = require('express');
var app = express();
//Added for connecting login session
var http = require('http');
var server = http.createServer(app);
var path = require('path');
var mongoose = require('mongoose');
var passport = require('passport');
var session = require('express-session');
var flash = require('connect-flash');
var async = require('async');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var methodOverride = require('method-override');
//connecting database
mongoose.connect("private mongoDB address");
var db = mongoose.connection;
db.once("open",function () {
console.log("DB connected!");
});
db.on("error",function (err) {
console.log("DB ERROR :", err);
});
var bcrypt = require("bcrypt-nodejs");
var userSchema = mongoose.Schema({
email: {type:String, required:true, unique:true},
password: {type:String, required:true},
createdAt: {type:Date, default:Date.now}
});
userSchema.pre("save", function (next){
var user = this;
if(!user.isModified("password")){
return next();
} else {
user.password = bcrypt.hashSync(user.password);
return next();
}
});
userSchema.methods.authenticate = function (password) {
var user = this;
return bcrypt.compareSync(password,user.password);
};
var User = mongoose.model('user',userSchema);
app.set("view engine", 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
//setting middleware for login
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(methodOverride("_method"));
app.use(flash());
app.use(session({secret:'MySecret', resave: true, saveUninitialized: true}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
//console.log('serializeUser()', user);
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
//console.log('deserializeUser()', user);
User.findById(id, function(err, user) {
done(err, user);
});
});
var global_username = '';
var LocalStrategy = require('passport-local').Strategy;
passport.use('local-login',
new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
User.findOne({ 'email' : email }, function(err, user) {
if (err) return done(err);
if (!user){
req.flash("email", req.body.email);
return done(null, false, req.flash('loginError', 'No user found.'));
}
if (!user.authenticate(password)){
req.flash("email", req.body.email);
return done(null, false, req.flash('loginError', 'Password does not Match.'));
}
var email_address = req.body.email;
var username = email_address.substring(0, email_address.lastIndexOf("#"));
global_username = username;
return done(null, user);
});
}
)
);
//set home routes
app.get('*', loggedInCheck); ------------------>This is the code with loggedInCheck function. I created another one instead of isLoggedIn function
app.get('/login', function (req,res) {
res.render('login/login',{email:req.flash("email")[0], loginError:req.flash('loginError')});
});
app.post('/login',
function (req,res,next){
next();
}, passport.authenticate('local-login', {
successRedirect : '/posts',
failureRedirect : '/login',
failureFlash : true
})
);
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/login');
});
// set user routes
app.get('/users/new', function(req,res){
res.render('users/new', {
formData: req.flash('formData')[0],
emailError: req.flash('emailError')[0],
passwordError: req.flash('passwordError')[0]
}
);
}); // new
app.post('/users', checkUserRegValidation, function(req,res,next){
User.create(req.body.user, function (err,user) {
if(err) return res.json({success:false, message:err});
res.redirect('/login');
});
}); // create
app.get('/posts', isLoggedIn, function(req, res){
res.redirect('/status.html?channel=' + global_username);
});
//functions
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()){
console.log("Authenticated");
console.log("Accessing to status.html");
return next();
}else{
console.log("Unauthorized Attempt");
res.redirect('/login');
}
}
function loggedInCheck(req, res, next) {
if (req.isAuthenticated()){
res.redirect('/status.html?channel=' + global_username);
}else{
console.log("Unauthorized Attempt");
res.redirect('/login');
}
}
server.listen(5000);
In Express, the order of calls matters.
In your case, the call to app.use (express.static... is done before the app.get ('/'... so it has a higher priority.
And since express.static ends the middleware chain, it will never call your app.get.
One possible solution would be to place your app.get above the app.use (express.static.
But, if you do so, you will never be able to show your index.html. You could add a condition to choose whether you redirect to /login or call next () to continue the middleware chain.
Edit
After taking a deeper look at your code, you seem to have a middleware isLoggedIn doing the proper logic.
You can keep the order of middlewares unchanged and do app.get('*', isLoggedIn);
This will call your middleware for any GET request.
You want to load '/login' before '/index.html' I assume you want the user to login before they reach the home page.
Also, instead of redirecting, try RENDERING.
Before using this code, reset your isLoggedIn back to default.
app.get('/', function(req, res) {
if(!isLoggedIn)
res.render('login')
else
res.redirect('/');
});
Hie, I split your app.js file into multiple parts in an effort to isolate the router, the files are given below.
app.js
var express = require('./express'),
mongoose = require('./mongoose'),
passport = require('./passport');
var db = mongoose();
var app = express();
var passport = passport();
app.listen(3000, function() {
console.log('Server running on port: ' + 3000);
});
express.js
var io = require('socket.io');
var express = require('express');
var app = express();
var redis = require('redis');
var sys = require('util');
var fs = require('fs');
//Added for connecting login session
var http = require('http');
var server = http.createServer(app);
var path = require('path');
var mongoose = require('mongoose');
var passport = require('passport');
var session = require('express-session');
var flash = require('connect-flash');
var async = require('async');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
module.exports = function() {
io = io.listen(server);
app.set("view engine", 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
//setting middleware for login
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(methodOverride("_method"));
app.use(flash());
app.use(session({secret: 'MySecret', resave: true, saveUninitialized: true}));
app.use(passport.initialize());
app.use(passport.session());
require('./passport');
require('./router')(app);
io.sockets.addListener('connection', function (socket) {
console.log("connceted : " + socket.id);
var subscriber = redis.createClient(6379, 'localhost');
subscriber.psubscribe("*");
subscriber.on("pmessage", function (pattern, channel, message) {
//console.log(message);
socket.emit(channel, message);
});
socket.on('disconnect', function () {
console.log("disconnceted : " + socket.id);
subscriber.quit();
});
socket.on('close', function () {
console.log("close");
subscriber.quit();
});
});
return app;
};
mongoose.js
var mongoose = require('mongoose');
module.exports = function() {
var db = mongoose.connect("mongodb://localhost/stacktest");
require('./model');
return db;
};
model.js
var mongoose = require('mongoose');
var bcrypt = require("bcrypt-nodejs");
var userSchema = mongoose.Schema({
email: {type:String, required:true, unique:true},
password: {type:String, required:true},
createdAt: {type:Date, default:Date.now}
});
userSchema.pre("save", function (next){
var user = this;
if(!user.isModified("password")){
return next();
} else {
user.password = bcrypt.hashSync(user.password);
return next();
}
});
userSchema.methods.authenticate = function (password) {
var user = this;
return bcrypt.compareSync(password,user.password);
};
mongoose.model('Users', userSchema);
passport.js
var passport = require('passport'),
LocalStrategy = require('passport-local');
module.exports = function() {
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
var LocalStrategy = require('passport-local').Strategy;
passport.use('local-login',
new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function (req, email, password, done) {
User.findOne({'email': email}, function (err, user) {
if (err) return done(err);
if (!user) {
req.flash("email", req.body.email);
return done(null, false, req.flash('loginError', 'No user found.'));
}
if (!user.authenticate(password)) {
req.flash("email", req.body.email);
return done(null, false, req.flash('loginError', 'Password does not Match.'));
}
return done(null, user);
});
}
)
);
};
And Finally router.js
var passport = require('./passport');
module.exports = function(app) {
app.get('/', function (req, res) {
res.redirect('/login');
//req.url = '/login';
//next();
});
app.get('/login', function (req, res) {
res.render('login', {email: req.flash("email")[0], loginError: req.flash('loginError')});
});
app.post('/login', function (req, res, next) {
passport.authenticate('local-login', function (err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.redirect('/login');
}
return res.redirect('/?channel=' + req.body.email);
})(req, res, next);
});
app.get('/logout', function (req, res) {
req.logout();
res.redirect('/login');
});
// set user routes
app.get('/users/new', function (req, res) {
res.render('users/new', {
formData: req.flash('formData')[0],
emailError: req.flash('emailError')[0],
passwordError: req.flash('passwordError')[0]
}
);
}); // new
};
I could not locate the 'checkUserRegValidation' so I had to remove (as I thought it was not directly related to the error in question), I then made two ejs files, with simple heading identifying the page (whether it the login page or index) and I got your expected result (The login page was rendered when put localhost://3000 in my browser). So maybe you could try to isolate your files if it helps, sorry for the long answer.
I'm trying to use passport local strategy in my app but the passport variable is undefined on the index.js route. Below is my codes from app.js, passport.js and my index.js route.
Here is my app.js:
var express = require("express");
var path = require('path');
var load = require("express-load");
var bodyParser = require("body-parser");
var cookieParser = require("cookie-parser");
var expressSession = require("express-session");
var methodOverride = require('method-override');
var passport = require('passport');
var error = require('./middlewares/error');
var app = express();
var server = require('http').Server(app);
global.mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test');
require('./config/passport')(passport);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(cookieParser('talkieparty'));
app.use(expressSession({
resave: false,
saveUninitialized: false,
secret: "149194"
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(methodOverride('_method'));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
load('models').then('controllers').then('routes').into(app, passport);
app.use(error.notFound);
app.use(error.serverError);
var User = app.models.user;
var moment = require('moment');
process.on('message', function(data) {//Executa um função ordenada pelo master.
console.log(process.pid + " executar: " + JSON.stringify(data));
var action = data.action;
switch(action) {
case "confirmation-email-sended":
var email = data.data.email;
User.findOne({email: email}, function(error, user) {
if(error) {
console.log(error);
}else {
if(!user) {
return console.log("No user was found with e-mail like " + email);
}
user.register.notified = true;
user.register.notified_date = new Date(moment().format());
user.save(function(error, user) {
if(error) {
console.log(error);
}else {
console.log("User " + user.email + " received the confirmation e-mail successfully!");
}
});
}
});
break;
default:
console.log("No action was found for " + action);
break;
};
});
server.listen(80, function() {
console.log("Listening!");
});
Here is my passport.js:
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-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function(req, email, password, done){
User.findOne({'email': email}, function(err, user) {
if(err) return done(err);
if(!user) return done(null, false, null);
if(!user.comparePasswordHashes(data.pass, user.register.password)) return done(null, false, null);
return done(null);
})
}));
}
And here is my index.js route where i'm getting the passport undefined:
module.exports = function(app, passport) {
var indexController = app.controllers.index;
app.get('/', indexController.index);
app.post('/login', indexController.login);
app.post('/register', indexController.register);
app.post('/passport', passport.authenticate('local-login', {
successRedirect: '/logado',
failureRedirect: '/falhou',
failureFlash: false
}));
};
The code
app.js:
var express = require('express');
var session = require('express-session');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoStore = require('connect-mongo')(session);
var mongoose = require('mongoose');
var passport = require('passport');
var config = require('./config');
var routes = require('./routes');
var mongodb = mongoose.connect(config.mongodb);
var app = express();
// view engine setup
app.set('views', config.root + '/views');
app.set('view engine', 'jade');
app.engine('html', require('ejs').renderFile);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cookieParser());
app.use(express.static(config.root + '/public'));
app.use(session({
name: 'myCookie',
secret: 'tehSecret',
resave: true,
saveUninitialized: true,
unset: 'destroy',
store: new mongoStore({
db: mongodb.connection.db,
collection: 'sessions'
})
}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', routes);
app.set('port', config.port);
var server = app.listen(app.get('port'), function() {
if (config.debug) {
debug('Express server listening on port ' + server.address().port);
}
});
routes.js:
var express = require('express');
var router = express.Router();
var config = require('../config');
var userController = require('../controllers/user');
var authController = require('../controllers/auth');
router.get('/', function(req, res) {
res.render('index', {
title: config.app.name
});
});
router.route('/users')
.post(userController.postUsers)
.get(authController.isAuthenticated, userController.getUsers);
router.get('/signout', userController.signout);
module.exports = router;
models/user.js:
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
var UserSchema = new mongoose.Schema({
username: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
}
});
// Execute before each user.save() call
UserSchema.pre('save', function(callback) {
var user = this;
// Break out if the password hasn't changed
if (!user.isModified('password')) return callback();
// Password changed so we need to hash it
bcrypt.genSalt(5, function(err, salt) {
if (err) return callback(err);
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return callback(err);
user.password = hash;
callback();
});
});
});
UserSchema.methods.verifyPassword = function(password, cb) {
bcrypt.compare(password, this.password, function(err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
};
// Export the Mongoose model
module.exports = mongoose.model('User', UserSchema);
controllers/user.js:
var config = require('../config');
var User = require('../models/user');
exports.postUsers = function(req, res) {
if (config.debug)
console.log("user.postUsers()");
var user = new User({
username: req.body.username,
password: req.body.password
});
user.save(function(err) {
if (err)
return res.send(err);
if (config.debug)
console.log("saved");
res.json({
message: 'New user created!'
});
});
};
exports.getUsers = function(req, res) {
if (config.debug)
console.log("user.getUsers()");
User.find(function(err, users) {
if (err)
return res.send(err);
if (config.debug)
console.log("users", users);
res.json(users);
});
};
exports.signout = function(req, res) {
if (config.debug)
console.log("user.signout()");
res.clearCookie('myCookie');
req.session.destroy(function(err) {
req.logout();
res.redirect('/');
});
};
controllers/auth.js:
var passport = require('passport');
var BasicStrategy = require('passport-http').BasicStrategy;
var config = require('../config');
var User = require('../models/user');
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(new BasicStrategy(
function(username, password, done) {
User.findOne({
username: username
}, function(err, user) {
if (err) {
return done(err);
}
// No user found with that username
if (!user) {
return done(null, false);
}
// Make sure the password is correct
user.verifyPassword(password, function(err, isMatch) {
if (err) {
return done(err);
}
// Password did not match
if (!isMatch) {
return done(null, false);
}
// Success
return done(null, user);
});
});
}
));
exports.isAuthenticated = passport.authenticate('basic', {
session: false
});
The problem
/signout route does not end the current session. In the req.session.destroy callback the req.session is undefined, yet a new GET request to /users acts like the session is valid.
Can someone help clear this problem out?
If, like me, you came here as a result of question title rather than full details- the answer is req.session.destroy(). I think the logout function is particular to passport.js and will not work if you are using standard express-session.
Solution
controllers/user.js:
exports.signout = function(req, res) {
if (config.debug)
console.log("user.signout()");
req.logout();
res.send(401);
};
Btw. don't mind the session(s) still being in DB immediately after the logout. Mongod checks and clears those out after 60 s.
in sign out api without using req.session.destroy() try req.logout();. I hope it will work.
In my case the server-side code was fine. It was the client-side code where I wasn't including the withCredentials parameter when making the http request.
Below is the correct working code.
// server side (nodejs)
authRouter.post("/logout",
passport.session(),
checkAuthenticationHandler,
async (req, res, next) => {
req.logOut(err => {
if (err) next(err)
res.status(http.statusCodes.NO_CONTENT).end()
})
})
// client side (reactjs)
export const logout = async () => {
const _response = await axios({
method: 'post',
url: `${authApi}/auth/logout`,
withCredentials: true
})
}