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 currently trying to get a node.js/express tutorial working (from Express in Action), but haven't been able to access a mongoose model properly. I call the module in a var called "User" I keep getting the error that "User.find is not a function."
Here is the models/user.js file:
var
bcrypt = require("bcrypt-nodejs"),
mongoose = require("mongoose"),
SALT_FACTOR = 10
;
var noop = function() {};
var userSchema = mongoose.Schema({
displayName: String,
bio: String
});
userSchema.pre("save", function(done) {
var user = this;
if (!user.isModified("password")) {
return done();
}
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if (err) { return done(err); }
bcrypt.hash(user.password, salt, noop, function(err, hashedPassword) {
if (err) { return done(err); }
user.password = hashedPassword;
done();
});
});
});
userSchema.methods.checkPassword = function(guess, done) {
bcrypt.compare(guess, this.password, function(err, isMatch) {
done(err, isMatch);
});
};
userSchema.methods.name = function() {
return this.displayName || this.username;
};
var User = mongoose.model("User", userSchema);
module.exports = User;
Here is the routes.js file calling it:
var
express = require("express"),
mongoose = require("mongoose"),
flash = require("connect-flash"),
passport = require("passport"),
router = express.Router()
;
var User = ("./models/user");
router.use(function(req, res, next){
res.locals.currentUser = req.user;
res.locals.errors = req.flash("error");
res.locals.infos = req.flash("info");
next();
});
router.get("/", function(req, res, next) {
User.find({}, function(err, users) {
assert.equal(err, null);
res.json(users);
});
});
/*
Original route, also doesn't work
router.get("/", function(req, res, next) {
User.find()
.sort({ createdAt: "descending" })
.exec(function(err, users) {
if (err) { return next(err); }
res.render("index", { users: users });
});
});
*/
module.exports = router;
Lastly here's the index.js file, in case it's relevant
var
http = require("http"),
path = require("path"),
express = require("express"),
flash = require("connect-flash"),
session = require("express-session"),
cookieParser = require("cookie-parser"),
logger = require("morgan"),
liquid = require("shopify-liquid"),
bodyParser = require("body-parser"),
mongoose = require('mongoose')
;
var routes = require('./routes');
var app = express();
mongoose.connect('mongodb://localhost:27017/test');
app.set("port", process.env.PORT || 3000);
var engine = liquid({
root: __dirname, // for layouts and partials
extname: '.liquid'
});
app.engine('liquid', engine.express());
app.set('views', ['./views', './views/partials', './views/layouts']);
app.set('view engine', 'liquid');
var assetsPath = path.resolve(__dirname, "assets");
app.use("/assets", express.static(assetsPath));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
secret: "TKRv0IJs=HYqrvagQ#&!F!%V]Ww/4KiVs$s,<<MX",
resave: true,
saveUninitialized: true
}));
app.use(flash());
app.use(routes);
app.use(logger("dev"));
app.use(function(request, response) {
response.status(404).render("404");
});
http.createServer(app).listen(3000, function(){
console.log('App skeleton started on port 3000.');
});
I've tried the solutions suggested from all similar questions but had no luck.
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 currently learning node, postgres, and passport but I am not sure on how to secure my application and best practices. I'm not sure on how to sanitize data from client and server or if it's needed but I've parameterized my queries. Any help would be greatly appreciated! Apologies for my newbieness.
var express = require('express');
var helmet = require('helmet')
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var passport = require('passport');
var passportLocal = require('passport-local');
var pg = require ('pg');
var bcrypt = require('bcryptjs');
var app = express();
app.use(helmet());
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var config = {
user: 'REDACTED',
database: 'REDACTED',
password: 'REDACTED',
host: 'REDACTED',
port: 5432,
max: 10,
idleTimeoutMillis: 30000,
};
var pool = new pg.Pool(config);
pool.on('error', function (err, client) {
console.error('idle client error', err.message, err.stack)
})
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(expressSession( {
secret: process.env.SESSION_SECRET || 'secret',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new passportLocal.Strategy(function(username, password, done) {
pool.connect(function(poolErr, poolClient, poolDone) {
if(poolErr) {
return console.error('pool client fetch error', poolErr);
}
poolClient.query('SELECT id, password FROM users WHERE username = $1', [username], function(queryErr, queryRes) {
if(queryErr) {
return console.error('query error', queryErr);
}
if(queryRes.rows[0] != undefined)
{
bcrypt.compare(password, queryRes.rows[0].password, function(compareErr, compareRes) {
if(compareErr) {
return console.error('bcrypt error', compareErr);
}
if(compareRes) {
done(null, { id: queryRes.rows[0].id });
} else {
done(null, null);
}
poolDone();
});
} else {
//user not found
poolDone();
done(null, null);
}
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
pool.connect(function(err, poolClient, poolDone) {
if(err) {
return console.error('pool client fetch error', err);
}
poolClient.query('SELECT * FROM users WHERE id = $1', [id], function(queryErr, queryRes) {
if(queryErr) {
return console.error('query error', queryErr);
}
if(queryRes.rows[0] != undefined)
{
done(null, { id: id, username: queryRes.rows[0].username, firstname: queryRes.rows[0].firstname, lastname: queryRes.rows[0].lastname });
} else {
//user not found
done(null, null);
}
poolDone();
});
});
});
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
res.render('index', {
isAuthenticated: req.isAuthenticated(),
user: req.user
})
});
app.get('/login', function(req, res) {
res.render('login');
});
app.post('/login', passport.authenticate('local'), function(req, res) {
res.redirect('/');
});
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
server.listen(8080);
console.log('Server is running...');
I don't see much problem but here is my 2 cent to improve it.
Use compression to reduce network size
app.use(require('compression'));
Use serve-static for static file like images or pdf
app.use(require('serve-static')('./public'))
Use middleware to control end point that need Authentication like view/edit profile, change password and etc
function authenticated(req, res, next) {
if (req.isAuthenticated()) next();
else {
res.status(401).send('User not authenticated.');
// or redirect to login
}
}
app.get('/profile', authenticated, function(req, res) {
res.render('profile', {
req.user
})
})
Include session destroy when logout
app.get('/logout', function(req, res) {
req.session.destroy();
req.logout();
res.redirect('/');
});
for sanitizing queries you can use ORM like sequelise
I am trying to create a sign up where the user if already existing in the db is logged into the system, or else a new user is created in the system.
So far I have come up with the following code.
//filename passport-config
var config = require('./config');
var passport = require('passport');
var User = require('./models/user');
var LocalStrategy = require('passport-local').Strategy;
var isValidPassword = function(user, password){
return bCrypt.compareSync(password, user.password);
};
// Generates hash using bCrypt
var createHash = function(password){
return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null);
}
// As with any middleware it is quintessential to call next()
// if the user is authenticated
var isAuthenticated = function (req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
passport.use('signup', new LocalStrategy({
passReqToCallback : true
},
function(req, email, password, done) {
findOrCreateUser = function(){
// find a user in Mongo with provided email
User.findOne({'email':email},function(err, user) {
// In case of any error return
if (err){
console.log('Error in SignUp: '+err);
return done(err);
}
// already exists
if (user) {
User.findOne({ 'email' : email },
function(err, user) {
if (!user){
console.log('User Not Found with email '+email);
return done(null, false);
}
// User exists but wrong password, log the error
if (!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null,false);
}
});
} else {
// if there is no user with that email
// create the user
var newUser = new User();
// set the user's local credentials
newUser.email = email;
newUser.password = createHash(password);
// save the user
newUser.save(function(err) {
if (err){
console.log('Error in Saving user: '+err);
throw err;
}
console.log('User Registration succesful');
return done(null, newUser);
});
}
});
};
// Delay the execution of findOrCreateUser and execute
// the method in the next tick of the event loop
process.nextTick(findOrCreateUser);
})
);
my router
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/timeslot',
failureRedirect: '/'
}));
my server.js file
var express = require('express');
var bodyParser = require('body-parser');
var leisure = require('leisure');
var cors = require('cors');
var passport = require('passport');
var config = require('./config');
var passportConfig = require('./passport-config');
var session = require('express-session')
var expressHbs = require('express-handlebars');
var mediaTypes = [
{ contentType: 'application/hal+json' },
{ contentType: 'application/json' },
{ contentType: 'text/html' }
];
var app = express();
/*Handlebars */
app.engine('handlebars', expressHbs({layout: false}) );
app.set('view engine', 'handlebars');
app.use(express.static(__dirname + '/assets'));
app.use(cors(config.settings.cors));
app.use(bodyParser());
app.use(leisure.accept(mediaTypes));
/*sessions */
app.use(session({
secret: 'keyboardSFS23432##!#!#at'
}));
app.use(passport.initialize());
app.use(passport.session());
var routes = require('./routes');
app.use('/', routes.router);
function start () {
var port = process.env.PORT || 3000;
app.listen(port);
console.log('Appoints service started on port ' + port);
}
exports.app = app;
exports.start = start;
The signup route doesn't work at all and I am pretty confused on how to debug this, any suggestions will be appreciated.
Have a look at the excellent article at
http://scotch.io/tutorials/javascript/easy-node-authentication-setup-and-local
and the sample code at
https://github.com/scotch-io/easy-node-authentication (with MongoDB), or
https://github.com/tobilg/easy-node-authentication-redis (with Redis as backend)