UnhandledPromiseRejectionWarning: Unhandled promise rejection in nodejs server - node.js

I am trying to use postman for the first time and yes i am a beginner with this authentication. I have a register page and a login page in angular and my backend is running on another port which is coded in nodejs. So i have installed passport and other required packages for the login authentication and registering user process. But on sending request to register route for registering a user i get the UnhandledPromiseRejectionWarning error. Even though there is then and catch inside the route it is still giving this error because of which i am confused. The data that i am sending is perfect but the error is occuring on the server side.
Here is my app.js file that contains all the routes
var express = require('express');
var mongoose = require('mongoose');
var bodyparser = require('body-parser');
var cors = require('cors');
var session = require('cookie-session');
var flash = require('connect-flash');
var passport = require('passport');
var bcrypt = require('bcryptjs');
require('./config/passport')(passport);
var User = require('./models/User');
var app = express();
app.use(bodyparser.json());
app.use(cors());
var expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: {
secure: true,
httpOnly: true,
domain: 'example.com',
path: 'foo/bar',
expires: expiryDate
}
}))
app.set('port', process.env.port || 3000);
app.use(passport.initialize());
app.use(passport.session());
// Connect flash
app.use(flash());
// Global variables
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');
next();
});
var db = mongoose.connect("mongodb://localhost:27017/server", {
useNewUrlParser: true
}, function(err, response) {
if (err) {
console.log('There is error in connecting with mongodb');
}
console.log('Connection has been established.');
});
app.get('/', (req, res) => {
res.send("hello");
});
//Trying registering with passport
app.post('/register', (req, res) => {
console.log(req.body);
debugger;
const { firstname, lastname, email, password } = req.body;
let errors = [];
if (errors.length > 0) {
res.render('register', {
errors,
name,
email,
password,
password2
});
} else {
User.findOne({ email: email }).then(user => {
if (user) {
errors.push({ msg: 'Email already exists' });
res.render('register', {
errors,
firstname,
lastname,
email,
password
});
} else {
const newUser = new User({
firstname,
lastname,
email,
password
});
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => {
req.flash(
'success_msg',
'You are now registered and can log in'
);
res.redirect('/login');
})
.catch(err => console.log(err));
});
});
}
});
}
});
//end
app.post('/login', (req, res, next) => {
console.log(req.body);
passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
failureFlash: true
})(req, res, next);
});
app.listen(app.get('port'), function(err, response) {
console.log("Server is running");
});
passport.js file in config folder
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// Load User model
const User = require('../models/User');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ emailField: 'email' }, (email, password, done) => {
// Match user
User.findOne({
email: email
}).then(user => {
if (!user) {
return done(null, false, { message: 'That email is not registered' });
}
// Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect' });
}
});
});
})
);
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
};

To resolve this specific issue, you need to provide a catch() when you execute User.findOne() at the same level as the outermost then():
User.findOne({ email: email })
.then(user => { /* existing code */})
.catch(err => console.log(err)); // add catch()
And:
// Match user
User.findOne({ email: email })
.then(user => { /* existing code */ })
.catch(err => console.log(err)); // add catch()
Regarding the issue with the engine. You need to specify a rendering engine such as pug or html or ejs, this is something that Express as a framework expects. The link you provided that you are basing this code off of is using a rendering engine, specifically ejs. This is evident from the use of res.render(), which renders templates from the "views" folder.
app.set('view engine', 'ejs');
Even with the rendering engine, set you don't actually need to render any templates. As long as you remove res.render() and instead just use res.send() or equivalent, you can use this Express application as an API.
If your intention is to NOT use templates but still render the built angular files, you need to update the code and remove all instances of res.render() and res.redirect(). You can instead, still setting a view engine to satisfy Express, do something along the following:
// towards top of file
app.use(express.static(path.join(__dirname, 'path/to/built/angular')));
// ...
// after all other routes
app.get('*', (req, res) =>{
res.sendFile(path.join(__dirname+'/path/to/built/angular/index.html'));
});
Hopefully that helps!

Related

My Web App Keeps Logging Me Out Node.js Express.js express-session

My website keeps logging me out when I try to access other pages when logged in. I am using cookies to store the session but, I guess I did not do it properly cause even after authentication, I am being continuously logged out. It is not letting me use my app.
Here is the link to my web-app: https://upset-gilet-lion.cyclic.app/
Here is my code:
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
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.use(express.static(__dirname + "/public/"));
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: true
}));
// Initializing Session
app.use(session({
secret: process.env.SECRET,
resave: false,
saveUninitialized: false
}));
// Initializing Passport
app.use(passport.initialize());
app.use(passport.session());
// Connecting to MongoDB using Mongoose
mongoose.set('strictQuery', true);
const mongodb = "mongodb://127.0.0.1:27017/userDB"
const mongodbNet = "mongodb+srv://admin-bhoami:"+ process.env.PASSWORD +"#secretscluster.uztbzho.mongodb.net/userDB";
mongoose.connect(mongodbNet, function(err){
if (err) {
console.log('Unable to connect to MongoDB');
console.log(err);
} else {
const PORT = process.env.PORT || 3000;
app.listen(PORT, function() {
console.log("Server started on Port ${PORT}");
console.log('Successfully connected to MongoDB');
});
}
});
// Creating a new User Database
const userSchema = new mongoose.Schema ({
email: String,
password: String,
googleId: String,
secret: Array
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
const User = new mongoose.model("User", userSchema);
// Set Local Login Strategy
passport.use(User.createStrategy());
// Serialize and Deserialize
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 that authenticates users using a Google Account and OAuth 2.0 tokens.
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "https://upset-gilet-lion.cyclic.app/auth/google/secrets", //"http://localhost:3000/auth/google/secrets"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({username: profile.emails[0].value, googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
// Home Page
app.route("/")
.get(function(req, res) {
res.render("home");
});
// Google Authentication Route
app.get('/auth/google',
passport.authenticate('google', { scope: ["openid", "profile", "email"] }));
app.get("/auth/google/secrets",
passport.authenticate("google", { failureRedirect: "/signin" }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect("/secrets");
});
// Sign-Up Page
app.route("/signup")
.get(function(req, res) {
res.render("signup");
})
.post(function(req, res) {
User.register({username: req.body.username}, req.body.password, function(err, user) {
if (err) {
console.log(err);
res.redirect("/signup");
} else {
passport.authenticate("local")(req, res, function() {
res.redirect("/secrets");
});
}
});
});
// Sign-In Page
app.route("/signin")
.get(function(req, res) {
res.render("signin");
})
.post(function(req, res) {
// Check database to see if the username provided exists in it.
User.findOne({username: req.body.username}, function(err, foundUser) {
// If username found, create an object "user" to store username and password which was used for login
if (foundUser) {
const user = new User ({
username: req.body.username,
password: req.body.password
});
// Use the "user" object to compare against username and password stored in Database.
// The code below will either return false is no match was found or it will return the 'found user'.
passport.authenticate("local", function (err, user) {
if (err) {
console.log(err);
} else {
// the 'user' below is the user returned from passport.authenticate callback; it will either be false if no match was found or the user
if (user) {
// If the user is found, then he/she is logged in or they are redirected to sign in page.
req.login(user, function(err) {
res.redirect("/secrets");
})
} else {
res.redirect("/signin");
}
}
}) (req, res);
// If no username is found, redirect to sign in page; i.e. user does not exists
} else {
res.redirect("/signin");
}
});
});
// Secrets Page
app.route("/secrets")
.get(function(req, res) {
if (req.isAuthenticated()) {
User.find({secret: {$ne: null}}, function(err, users) {
if (!err) {
if (users) {
res.render("secrets", {usersWithSecrets: users});
} else {
console.log(err);
}
} else {
console.log(err);
}
});
} else {
res.redirect("/signin");
}
});
// Sign-Out Route
app.route("/signout")
.get(function(req, res) {
req.logout(function(err) {
if (err) {
console.log(err);
} else {
res.redirect("/")
}
});
});
// Submit Route
app.route("/submit")
.get(function(req, res) {
if (req.isAuthenticated()) {
res.render("submit");
} else {
res.redirect("/signin");
}
})
.post(function(req, res) {
const submittedSecret = req.body.secret;
if(req.isAuthenticated()) {
req.user.secret.push(submittedSecret);
req.user.save(function() {
res.redirect("/secrets");
})
} else {
res.redirect("/signin");
}
});
// Delete Route
app.route("/delete")
.get(function(req, res) {
if (req.isAuthenticated()) {
res.render("delete", {secrets: req.user.secret});
} else {
res.redirect("/signin");
}
})
.post(function(req, res) {
if(req.isAuthenticated()){
User.findById(req.user.id, function (err,foundUser){
foundUser.secret.splice(foundUser.secret.indexOf(req.body.secret),1);
foundUser.save(function (err) {
if(!err){
res.redirect("/secrets");
}
});
});
}else {
res.redirect("/signin");
}
});
Turns out it wasn't a problem with my MongoDB connection. It was a problem with session storage. I used the 'connect-mongo' (https://www.npmjs.com/package/connect-mongo) package from npm and the web app started working as expected.
All I had to do:
npm install connect-mongo
const MongoStore = require('connect-mongo');
app.use(session({
store: MongoStore.create({mongoUrl: "mongodb://127.0.0.1:27017/databaseName"})
}));

User Authentication not working as expected

I created a web app that authenticates users using Passport.js where they are able to log-in or register either using the web form or google authentication. The web app is working fine and as expected locally, however, when deployed, it is allowing me to register but, when logged in, I try to press any button, it logs me out asks me to sign in again. The log is giving me a bunch of 304 and 302 status code errors. I don't know what is wrong. Please help.
Once I log in, I expect it to keep me logged in until I sign out. Instead, once I log in and try to use the web app, it logs me out. I am using: express, mongoose, session, express-passport, passport-local-mongoose, passport-google-oauth20, mongoose-findorcreate
Here is the link to my deployed web app: https://upset-gilet-lion.cyclic.app/
Here is a screenshot of deployed app logs:
logs screenshot
Here is my app.js code:
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
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.use(express.static(__dirname + "/public/"));
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: true
}));
// Initializing Session
app.use(session({
secret: process.env.SECRET,
resave: false,
saveUninitialized: false
}));
// Initializing Passport
app.use(passport.initialize());
app.use(passport.session());
// Connecting to MongoDB using Mongoose
mongoose.set('strictQuery', true);
const mongodb = "mongodb://127.0.0.1:27017/userDB"
const mongodbNet = "mongodb+srv://admin-bhoami:"+ process.env.PASSWORD +"#secretscluster.uztbzho.mongodb.net/userDB";
mongoose.connect(mongodbNet, function(err){
if (err) {
console.log('Unable to connect to MongoDB');
console.log(err);
} else {
console.log('Successfully connected to MongoDB');
}
});
// Creating a new User Database
const userSchema = new mongoose.Schema ({
email: String,
password: String,
googleId: String,
secret: Array
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
const User = new mongoose.model("User", userSchema);
// Set Local Login Strategy
passport.use(User.createStrategy());
// Serialize and Deserialize
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 that authenticates users using a Google Account and OAuth 2.0 tokens.
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "https://upset-gilet-lion.cyclic.app/auth/google/secrets", //"http://localhost:3000/auth/google/secrets"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({username: profile.emails[0].value, googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
// Home Page
app.route("/")
.get(function(req, res) {
res.render("home");
});
// Google Authentication Route
app.get('/auth/google',
passport.authenticate('google', { scope: ["openid", "profile", "email"] }));
app.get("/auth/google/secrets",
passport.authenticate("google", { failureRedirect: "/signin" }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect("/secrets");
});
// Sign-Up Page
app.route("/signup")
.get(function(req, res) {
res.render("signup");
})
.post(function(req, res) {
User.register({username: req.body.username}, req.body.password, function(err, user) {
if (err) {
console.log(err);
res.redirect("/signup");
} else {
passport.authenticate("local")(req, res, function() {
res.redirect("/secrets");
});
}
});
});
// Sign-In Page
app.route("/signin")
.get(function(req, res) {
res.render("signin");
})
.post(function(req, res) {
// Check database to see if the username provided exists in it.
User.findOne({username: req.body.username}, function(err, foundUser) {
// If username found, create an object "user" to store username and password which was used for login
if (foundUser) {
const user = new User ({
username: req.body.username,
password: req.body.password
});
// Use the "user" object to compare against username and password stored in Database.
// The code below will either return false is no match was found or it will return the 'found user'.
passport.authenticate("local", function (err, user) {
if (err) {
console.log(err);
} else {
// the 'user' below is the user returned from passport.authenticate callback; it will either be false if no match was found or the user
if (user) {
// If the user is found, then he/she is logged in or they are redirected to sign in page.
req.login(user, function(err) {
res.redirect("/secrets");
})
} else {
res.redirect("/signin");
}
}
}) (req, res);
// If no username is found, redirect to sign in page; i.e. user does not exists
} else {
res.redirect("/signin");
}
});
});
// Secrets Page
app.route("/secrets")
.get(function(req, res) {
if (req.isAuthenticated()) {
User.find({secret: {$ne: null}}, function(err, users) {
if (!err) {
if (users) {
res.render("secrets", {usersWithSecrets: users});
} else {
console.log(err);
}
} else {
console.log(err);
}
});
} else {
res.redirect("/signin");
}
});
// Sign-Out Route
app.route("/signout")
.get(function(req, res) {
req.logout(function(err) {
if (err) {
console.log(err);
} else {
res.redirect("/")
}
});
});
// Submit Route
app.route("/submit")
.get(function(req, res) {
if (req.isAuthenticated()) {
res.render("submit");
} else {
res.redirect("/signin");
}
})
.post(function(req, res) {
const submittedSecret = req.body.secret;
if(req.isAuthenticated()) {
req.user.secret.push(submittedSecret);
req.user.save(function() {
res.redirect("/secrets");
})
} else {
res.redirect("/signin");
}
});
// Delete Route
app.route("/delete")
.get(function(req, res) {
if (req.isAuthenticated()) {
res.render("delete", {secrets: req.user.secret});
} else {
res.redirect("/signin");
}
})
.post(function(req, res) {
if(req.isAuthenticated()){
User.findById(req.user.id, function (err,foundUser){
foundUser.secret.splice(foundUser.secret.indexOf(req.body.secret),1);
foundUser.save(function (err) {
if(!err){
res.redirect("/secrets");
}
});
});
}else {
res.redirect("/signin");
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, function() {
console.log("Server started on Port ${PORT}");
});

Unable to get Passport working with React & Node, without Passport authentication works fine

This is my first try with PassportJS, and I am following their documentation, which is very hard to understand for me.
My goal is to have a user register through Registration Page, a react component and then use the Login page, a react component as well, to login and redirect to a Dashboard, which is again a react component.
All the above works, but without Passport. I am not sure what I am doing wrong, as this is my first time working with it, but it seems to not working. And by not working I mean that I don't see any error message and the login page is not redirecting to dashboard.
Although I have managed to almost put things together, somehow either I am missing something or doing something wrong.
This is my React Login Component, which is sending Axios post request to API:
const onSubmit = (e) => {
e.preventDefault();
const newLogin = {
username,
password,
};
const config = {
headers: {
'Content-Type': 'application/JSON',
},
};
axios.post('/api/v1/login', newLogin, config).then((res) => {
return res.data === 'user'
? (window.location = '/dashboard')
: (window.location = '/login');
});
setUsername('');
setPassword('');
};
On Node server.js, the above login post request is sent to controller through router.
server.js:
app.use(passport.initialize());
app.use(passport.session());
app.use('/api/v1/register', register);
app.use('/api/v1/login', login);
Router.js (Login):
const { loginUser } = require('../controllers/loginController');
router.route('/').post(loginUser);
loginController.js:
require('../config/passport')(passport);
exports.loginUser = (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/register',
failureFlash: true,
});
};
This is my passport.js file:
const User = require('../models/UserModel');
const passport = require('passport');
module.exports = function (passport) {
passport.use(
new LocalStrategy((username, password, done) => {
// Match User
User.findOne({ username: username })
.then((err, user) => {
if (!user) {
return done(null, false, console.log('no user'));
}
//Match Password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect' });
}
});
})
.catch((err) => console.log(err));
})
);
};
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findOne(id, (err, user) => {
done(err, user);
});
});
I'd suggest removing the redirects from the passport login controller and handling the routing from the react app internally (via react router or otherwise) based on whether or not the app received a user in the response. Here's how I've got it set up in my recent project:
//router.js
const express = require("express");
const fs = require("fs");
const { userModel } = require("../models");
const passport = require("passport");
const bcrypt = require("bcrypt");
const bodyParser = express.urlencoded({ extended: true, limit: "50mb" });
const jsonParser = express.json({ limit: "50mb" });
const router = express.Router();
const saltRounds = 10;
router.get("/login", (req, res) => {
res.render("login");
});
router.get("/logout", (req, res, next) => {
req.logout();
req.session.destroy();
next();
});
router.post("/login", bodyParser, jsonParser, **passport.authenticate("local"),** (req, res, next) => {
if (!req.user) return;
const date = new Date();
console.log(`User ID:${req.user._id} logged in at ${date}`);
res.json(req.user);
next();
});
module.exports = router;
Note how I'm just using passport as middleware, then move on to the next function, which checks for the user it should have received from the previous function

Error: No default engine was specified and no extension was provided in node server

I am using nodejs as backend server while my frontend is in angular. I need to call the register router and for that i am sending the data from frontend in json fromat which is perfect but since i am trying to passport authentication here, i took passport authentication code from another github repository in which node was also using an engine so that's why res.render was used in it. But now i am finding it difficult to remove this particular line from the register router and if i try to delete it or just use res.sendStatus(500) it still does not work and i get 500 error. What could be the solution of this problem?
var express = require('express');
var mongoose = require('mongoose');
var bodyparser = require('body-parser');
var cors = require('cors');
var session = require('cookie-session');
var flash = require('connect-flash');
var passport = require('passport');
var bcrypt = require('bcryptjs');
require('./config/passport')(passport);
var User = require('./models/User');
var app = express();
app.use(bodyparser.json());
app.use(cors());
var expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: {
secure: true,
httpOnly: true,
domain: 'example.com',
path: 'foo/bar',
expires: expiryDate
}
}))
app.set('port', process.env.port || 3000);
app.use(passport.initialize());
app.use(passport.session());
// Connect flash
app.use(flash());
// Global variables
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');
next();
});
var db = mongoose.connect("mongodb://localhost:27017/server", {
useNewUrlParser: true
}, function(err, response) {
if (err) {
console.log('There is error in connecting with mongodb');
}
console.log('Connection has been established.');
});
app.get('/', (req, res) => {
res.send("hello");
});
//Trying registering with passport
app.post('/register', (req, res) => {
console.log(req.body);
const { firstname, lastname, email, password } = req.body;
let errors = [];
if (errors.length > 0) {
res.render('register', {
errors,
name,
email,
password,
password2
});
} else {
User.findOne({ email: email }).then(user => {
if (user) {
errors.push({ msg: 'Email already exists' });
res.render('register', {
errors,
firstname,
lastname,
email,
password
});
} else {
const newUser = new User({
firstname,
lastname,
email,
password
});
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => {
req.flash(
'success_msg',
'You are now registered and can log in'
);
res.redirect('/login');
})
.catch(err => console.log(err));
});
});
}
})
.catch(err => console.log(err))
}
});
//end
app.post('/login', (req, res, next) => {
console.log(req.body);
passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
failureFlash: true
})(req, res, next);
});
app.listen(app.get('port'), function(err, response) {
console.log("Server is running");
});
You are using res.render() in the callback function in app.post('/register', callback). If res.render() is called it will look for a template (probably in a views directory). If you have not specified which engine to use you will get that error.

PassportJs Authentication Infinite Loop and Execute(default) query

I am trying to build the authentication system using PassportJs and Sequelize. I made the registration system by myself, using Sequelize. I want to use PassportJS only for Login.
It does not redirect me to the failureRedirect route, neither to the SuccessRedirect one, but when submitting the form it enters into an endless loop and in my console, the following message appears:
Executing (default): SELECT `id`, `username`, `lastName`, `password`, `email`, `phone`, `createdAt`, `updatedAt` FROM `user` AS `user` LIMIT 1;
My project is structured in: users_model.js , index.js and users.js (the controller).
The code I have in my index.js looks like this:
//===============Modules=============================
var express = require('express');
var bodyParser = require('body-parser');
var session = require('express-session');
var authentication= require('sequelize-authentication');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var passportlocal= require('passport-local');
var passportsession= require('passport-session');
var User = require('./models/users_model.js');
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
console.log(id);
});
});
var users= require('./controllers/users.js');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/users', users);
app.use('/events', events);
//-------------------------------------------Setup Session------------
app.use(session({
secret: "ceva",
resave:true,
saveUninitialized:true,
cookie:{},
duration: 45 * 60 * 1000,
activeDuration: 15 * 60 * 1000,
}));
// Passport init
app.use(passport.initialize());
app.use(passport.session());
//------------------------------------------------Routes----------
app.get('/', function (req, res) {
res.send('Welcome!');
});
//-------------------------------------Server-------------------
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
In my controller, I made the registration system by myself, using Sequelize. In users.js, I have:
var express = require('express');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var passportlocal= require('passport-local');
var passportsession= require('passport-session');
var router = express.Router();
var User = require('../models/users_model.js');
//____________________Initialize Sequelize____________________
const Sequelize = require("sequelize");
const sequelize = new Sequelize('millesime_admin', 'root', '', {
host: 'localhost',
dialect: 'mysql',
pool: {
max: 5,
min: 0,
idle: 10000
}
});
//________________________________________
router.get('/',function(req,res){
res.send('USERS');
});
router.get('/register', function(req, res) {
res.render('registration', {title: "Register" });
});
router.post('/register', function(req, res) {
var email = req.body.email;
var password = req.body.password;
var username= req.body.username;
var lastname= req.body.lastname;
var phone= req.body.phone;
User.findAll().then(user => {
usersNumber = user.length;
x=usersNumber+1;
var y =usersNumber.toString();
var uid='ORD'+ y;
User.sync().then(function (){
return User.create({
id:uid,
email: email,
password:password,
username: username,
lastName: lastname,
phone: phone,
});
}).then(c => {
console.log("User Created", c.toJSON());
res.redirect('/users');
}).catch(e => console.error(e));
});
});
router.get('/login',function(req,res){
res.render('authentication');
});
//router.post('/login', function(req, res, next) {
// console.log(req.url); // '/login'
// console.log(req.body);
// I got these:{ username: 'username', password: 'parola' }
// passport.authenticate('local', function(err, user, info) {
// console.log("authenticate");
// console.log('error:',err);
// console.log('user:',user);
// console.log('info:',info);
// })(req, res, next);
//});
router.post('/login', passport.authenticate('local', {
successRedirect: '/events',
failureRedirect: '/users/register'
}));
router.get('/logout', function(req, res){
req.logout();
res.redirect('/users/login');
});
//__________________________________________
module.exports = router;
Main problem: not an infinite loop, but incorrect usage of Sequelize
This is not an infinite loop but just a hanging response from the server which would be ended with a timeout error.
When you do this:
passport.use(new LocalStrategy(
function(username, password, done) {
...
}
));
...passport and express wait for the done function to be called. Once it's done(), they go forward in the middleware chain and send the response to the client.
The done function is not called, because Sequelize seems to not support callback functions, but promises. So, the correct way to call Sequelize methods is:
User.findOne({ username: username }).then(user => {
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
done(null, user);
}).catch(err => done(err));
(de)Serializing the session user
Seems that there is no id field in the user instances, but userid. Therefore we have to do:
passport.serializeUser(function(user, done) {
done(null, user.userid);
});
passport.deserializeUser(function(id, done) {
User.findOne({ userid: id }).then(user => {
done(null, user);
console.log(id);
}).catch(err => done(err));
});
For reference, this commit fixes these issues.

Resources