Mongoose connection sockets closed - node.js

I'm using nodejs and MongoDB for the first time and I'm having trouble when I want to connect to the DB.
I read the quickstart from mongoosejs but it still doesn't work, here is my code (right now, all my code is only in one file) :
/***** Utilities *****/
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var path = require('path');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongo = require('mongodb');
var mongoose = require('mongoose');
app.listen(8080);
mongoose.connect('mongodb://localhost:8080/users');
var db = mongoose.connection;
db.on('error', function (error) {
console.log('/**************** ERROR **************\\');
console.log(error);
});
db.on('open', function () {
console.log("Hello World!");
});
var Schema = mongoose.Schema;
var UserSchema = new Schema({
pseudo: String,
password: String,
email: String
});
var Users = mongoose.model('users', UserSchema);
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname + '/views');
app.use(passport.initialize());
app.use(passport.session());
/***** Passport *****/
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
/***** Building routes *****/
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.post('/', function (req, res) {
var pseudo = req.body.pseudo;
console.log("/******************************\\") console.log(pseudo);
res.send('Hello ' + pseudo + '!');
});
app.get('/users', function (req, res) {
Users.find(function (error, users) {
if (error) console.log(error);
else res.render('users.jade', {
users: users
})
});
})
app.post('/create_user', function (req, res) {
var user = new Users({
pseudo: req.body.pseudo,
password: req.body.password,
email: req.body.email
});
user.save(function (error, user) {
if (error) console.log(error);
else res.render('create_user.jade');
});
});
app.get('/login', function (req, res) {
passport.authenticate('users', {
successRedirect: '/create_user',
failureRedirect: '/login',
}) res.render('login.jade
);
});
I'm trying to get data from the login page and store them into one mongo database but I'm when I start this file, mongo returns the following message:
MongoError: server localhost:8080 sockets closed
name: 'MongoError',
message: 'server localhost:8080 sockets closed'
I really don't know how to correct this error.
Where am I wrong? Is it because of a possible asynchronous problem?

Related

req.isAuthenticated() always returns false

I am new to the Passport.js. Whenever I login or register through the routes, req.isAuthenticated() always returns false and the secrets view is never rendered. Here is my app.js:
`
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy = require("passport-local")
const passportLocalMongoose = require("passport-local-mongoose");
const mongoose = require("mongoose");
mongoose.set("strictQuery", true);
uri = "mongodb://localhost:27017/usersDB";
const userSchema = new mongoose.Schema({
username: String,
password: String
});
userSchema.plugin(passportLocalMongoose);
const User = new mongoose.model("User", userSchema);
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
const app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(session({
secret: "MyLittleSecret",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.get("/", function(req, res) {
res.render("home");
});
app.get("/secrets", function(req, res) {
if(req.isAuthenticated) {
res.render("secrets");
} else {
res.redirect("/login");
}
});
app.route("/register")
.get(function(req, res) {
res.render("register");
})
.post(async function(req, res) {
await User.register({username: req.body.username}, req.body.password, function(err, user) {
console.log("In the User.register callback function");
if(err) {
console.log(err);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, function() {
res.redirect("/secrets");
});
}
});
});
app.route("/login")
.get(function(req, res) {
res.render("login",{
errorMessage: ""
});
})
.post(async function(req, res) {
const userInstance = new User({
username: req.body.username,
password: req.body.password
});
req.login(userInstance, function(err) {
if(err) {
console.log(err);
} else {
passport.authenticate("local")(req,res,function() {
res.redirect("/secrets");
});
}
});
});
app.listen(3000, function() {
console.log("Server started listening to port 3000");
});
I searched on the web and tried the various orders of middleware. I could not solve the problem.

Level 1 authentication

Good day, Please help me find the error in my code for level one authentication I could create a database, register users and store in their inputs using body parser, but I couldn't login already registered users. the login page keeps loading till it tells me a connection error, please help me out
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const app = express();
app.use(express.static("public"));
app.set('view-engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: true
}));
mongoose.connect("mongodb://localhost:27017/User", {useNewUrlParser: true});
const userSchema = ({
email: String,
password: String
});
const User = new mongoose.model("User", userSchema);
const users = []
app.get("/", function(req, res){
res.render("first.ejs");
});
app.get("/login", function(req, res){
res.render("login.ejs");
});
app.get("/register", function(req, res){
res.render("register.ejs");
});
app.post("/register", function(req, res){
const newUser = new User({
email: req.body.username,
password: req.body.password
});
newUser.save(function(err){
if (err) {
console.log(err);
} else {
res.render("home.ejs");
}
});
});
app.post("/login", function(req, res){
const username = req.body.username;
const password = req.body.password;
User.findOne({email: username}, function(err, foundUser){
if (err) {
console.log(err);
} else {
if (foundUser) {
if (foundUser.password === password) {
res.send("hi");
}
}
}
});
});
app.listen(3000, function() {
console.log("Server started on port 3000.");
});

displaying current number of unique users on website using nodejs

I'm trying to display number of current users on a particular page on my website. I got to know about socket.io for doing this exact particular thing but every solution on the internet had a separate server.js file to make it work. My question is, how do I implement this using app.js which I have already configured for my website's use, listening on port 3000. Sorry if my question is a little naive but I've recently started web development and don't know exactly how to do this.
My app.js is as follows:
//jshint esversion:6
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const ejs = require('ejs');
const _ = require('lodash');
const mongoose = require('mongoose');
const session = require('express-session');
const passport = require('passport');
const passportLocalMongoose = require('passport-local-mongoose');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const findOrCreate = require('mongoose-findorcreate');
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
//Passport Sessions setup
app.use(session({
secret: "Our little secret.",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
// Users DB
let conn = mongoose.createConnection("mongodb+srv://#cluster0.wrvir.mongodb.net/userDB", {useNewUrlParser: true, useUnifiedTopology: true});
// conn.set("useCreateIndex", true);
const userSchema = new mongoose.Schema ({
username: String,
// password:String,
googleId: String
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
const User = conn.model("User", userSchema);
passport.use(User.createStrategy());
passport.serializeUser(function(user, done){
done(null, user.id);
});
passport.deserializeUser(function(id, done){
User.findById(id, function(err, user){
done(err, user);
});
});
// Google Authentication Strategy
passport.use(new GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/timeline",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
console.log(profile);
User.findOrCreate({ googleId: profile.id, username: profile.displayName }, function (err, user) {
return cb(err, user);
});
}
));
// Stories DB
let conn2 = mongoose.createConnection("mongodb+srv://#cluster0.wrvir.mongodb.net/storiesDB", {useNewUrlParser: true, useUnifiedTopology: true});
const postSchema = {
title: String,
content: String
};
const Post = conn2.model("Post", postSchema);
app.get("/", function(req, res){
res.render("home");
});
app.get("/auth/google",
passport.authenticate("google", { scope: ["profile"] })
);
app.get("/auth/google/timeline",
passport.authenticate("google", { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, redirect to timeline.
res.redirect('/timeline');
});
app.get("/posts/:postid", function(req, res){
const requestedPostId = req.params.postid;
Post.findOne({_id: requestedPostId}, function(err, post){
res.render("post", {
title: post.title,
content: post.content
});
});
});
app.get("/compose", function(req, res){
res.render("compose");
});
app.post("/compose", function(req, res){
const post = new Post({
title: req.body.postTitle,
content: req.body.postBody
});
post.save(function(err){
if (!err){
res.redirect("/timeline");
}
});
});
app.get("/timeline", function(req, res){
if(req.isAuthenticated()){
Post.find({},function(err, posts){
res.render("timeline", {
startingContent: homeStartingContent,
posts: posts
});
});
} else {
res.redirect("/login");
}
});
app.get("/logout", function(req, res){
req.logout();
res.redirect("/");
});
app.listen(process.env.PORT || 3000, function(){
console.log("Server started on port 3000...");
});
Server side
The `app.listen` function at the end of your code returns a `server` object, which can then be used to setup a socket like that:
const socketio = require('socket.io');
// ...
const PORT = process.env.PORT || 3000;
const server = app.listen(PORT, () => console.log(`Server started on port ${PORT}.`));
const io = socketio(server);
Then you could have the following logic to count your users and emit an event to every user, if the count changes:
let userCount = 0;
io.on('connection', socket => {
userCount++;
io.emit('user-count-change', userCount);
socket.on('disconnect', () => {
userCount--;
io.emit('user-count-change', userCount);
});
});
Optional
But since this code would constantly emit events to every user on every connection, the number of emits would grow exponentially. As a solution I'd fire events in an interval with a bit of delay in between:
const userCountUpdateDelay = 10000;
let userCount = 0;
io.on('connection', socket => {
userCount++;
socket.on('disconnect', () => { userCount--; });
socket.emit('user-count-change', userCount);
});
setInterval(() => {
io.emit('user-count-change', userCount);
}, userCountUpdateDelay);
Client side
Add this html somewhere to a your website:
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
socket.on('user-count-change', function (userCount) {
console.log(userCount);
// Display the user count...
});
</script>
Learn more
If you wanna learn more about socket.io, it has a great documentation, which you can find here

How to show login page before showing index.html using express.static in node.js

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.

express-session won't log out

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
})
}

Resources