passportjs validate on signup if user already exists - node.js

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)

Related

Node.js passport not authenticating at login

I am trying to implement a simple user login and signup page for my application.
The signup page works and everything is getting stored in mongodb correctly. However, when I try to login it it does not seem to work. It is supposed to redirect to my root page but it will not do that. It always redirect back to /users/login
I've been going through a tutorial online so I do not understand why this isn't working. Here are the relevant files files.
user.js file
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
let User = require('../models/user');
// Load register form
router.get('/register', function(req, res) {
res.render('register', {
title : 'Register',
errors : req.flash('success')
});
});
// Submit register form
router.post('/register', function(req, res) {
// Get the fields from the form
const firstname = req.body.firstname;
const lastname = req.body.lastname;
const email = req.body.email;
const pass = req.body.pass;
const pass2 = req.body.pass2;
// Verify body is not empty.
req.checkBody('firstname', 'First name is required').notEmpty();
req.checkBody('lastname', 'Last name is required').notEmpty();
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
req.checkBody('pass', 'Password is required').notEmpty();
req.checkBody('pass2', 'Passwords do not match.').equals(req.body.pass);
// Check for errors
let errors = req.validationErrors();
if (errors) {
res.render('register', {
errors:errors
});
} else {
// Create new user object
let newUser = new User({
firstname:firstname,
lastname:lastname,
email:email,
pass:pass
});
// Hash the password for security.
bcrypt.genSalt(10, function(err, salt){
bcrypt.hash(newUser.pass, salt, function(err, hash) {
if (err) {
console.log(err);
}
newUser.pass = hash;
newUser.save(function(err) {
if (err) {
console.log(err);
return;
} else {
console.log("Successful creation.")
req.flash('success', 'Account creation successful!');
res.redirect('/users/login');
}
});
});
})
}
});
// Load login form
router.get('/login', function(req, res){
res.render('login');
});
// Submit login form
router.post('/login', function(req, res, next) {
passport.authenticate('local', {
successRedirect: '..',
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
});
module.exports = router;
passport.js file
const LocalStrategy = require('passport-local').Strategy;
const passport = require('passport');
const User = require('../models/user');
const config = require('../config/database');
const bcrypt = require('bcryptjs');
// User Authentication
module.exports = function(passport){
console.log("Made it intro str");
passport.use(new LocalStrategy(function(email, pass, done){
// Match username
let query = {email:email};
User.findOne(query, function(error, user){
if (error){
console.log("error");
return done(error);
}
if (!user) {
console.log("No user found");
return done(null, false, {message: 'No user found.'});
}
bcrypt.compare(pass, user.pass, function(error, isMatch) {
if (error) {
console.log("error2");
return done(error);
}
if (isMatch) {
console.log("Matching password");
return done(null, user);
} else {
console.log("Wrong password");
return done(null, false, {message: 'Invalid password.'});
}
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
}
App.js
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const logger = require('morgan');
const session = require('express-session');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const expressValidator = require('express-validator');
const config = require('./config/database');
const flash = require('connect-flash');
const passport = require('passport');
/* Connect to Database */
mongoose.connect(config.database, { useNewUrlParser: true });
let db = mongoose.connection;
// Check connection.
db.once('open', function(){
console.log('Connected to MongoDB.');
})
// Check DB error.
db.on('error', function(error){
console.log(error);
});
/* Initialize app */
var app = express();
/* Bring in models for database */
let User = require('./models/user');
// Body Parser Middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Load the view engines
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// Set public folder
app.use(express.static(path.join(__dirname, 'public')));
app.use(expressValidator());
// Keep users session
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}));
app.use(require('connect-flash')());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
// Express Validator Middleware
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
// Passport config
require('./config/passport')(passport);
app.use(passport.initialize());
app.use(passport.session());
// Load homepage
app.get('/', function(req, res) {
res.render('index', {
title: 'Index',
})
})
// Define routes
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/user');
app.use('/', indexRouter);
app.use('/users', usersRouter)
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
;
module.exports = app;
I believe the issue is in your passport.js file... By default, LocalStrategy expects to find credentials in parameters named username and password. You need to change that... something like so:
const localOptions = { usernameField: 'email', passwordField: 'pass' };
passport.use(new LocalStrategy(localOptions, function (email, pass, done) {
// Match username
let query = { email: email };
User.findOne(query, function (error, user) {
// etc etc...
});
}));
Link to the docs (at the bottom of the page...): http://www.passportjs.org/docs/username-password/

Cannot call Passport local strategy

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.

How to make API call using API token in Node.js using express, passport-local

I'm a newbie in Node.js and trying to use API token to access Grafana.
And I created one API token by following instruction from Grafana page.
However, I don't know how to make API calls from my code of node.js to access my local server of grafana page. Also, I have a local login-page by using mongoDB to manage users.
How can I make Node.js API calls to access my local server of grafana page?
Please help me out here.. I'm having hard time on this..
If you want me to show code, I can edit here..
EDIT:
This is my whole code for 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');
//Adding grafana
var request = require('request');
//Connecting Database (MongoDB)
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);
});
//Setting bcrypt for password.
var bcrypt = require("bcrypt-nodejs");
//Setting userSchema for MongoDB.
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();
}
});
//setting bcrypt for password.
userSchema.methods.authenticate = function (password) {
var user = this;
return bcrypt.compareSync(password,user.password);
};
//Setting User as userSchema.
var User = mongoose.model('user',userSchema);
io = io.listen(server);
//Setting middleware for login format.
app.set("view engine", 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
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());
//Initializing passport.
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 username_tmp = '';
var global_username = ''; //Global variable for username to put in the address
var pass = '';
//Initializing passport-local strategy.
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;
username_tmp = email_address;
var username = email_address.substring(0, email_address.lastIndexOf("#"));
global_username = username;
pass = req.body.password;
return done(null, user);
});
}
)
);
//Check whether it is logged in or not.
//If it is not logged in(Session is out), it goes to login page
//If it is logged in(Session is still on), it goes directly to status.html
app.get('/', loggedInCheck);
app.get('/login', function (req, res) {
res.render('login/login',{email:req.flash("email")[0], loginError:req.flash('loginError')});
});
//Accessing to MongoDB to check to login or not
app.post('/login',
function (req,res,next){
next();
}, passport.authenticate('local-login', {
successRedirect : '/status',
failureRedirect : '/login',
failureFlash : true
})
);
//Creating new account
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]
}
);
});
//Calling status.html
app.get('/status', isLoggedIn, function(req, res){
var user_temp = {user: ''};
user_temp.user = global_username;
res.render('status/status', user_temp);
//res.redirect('/status.html?channel=' + global_username);
});
app.get('/grafana', isLoggedIn, function(req, res){
console.log('Accessing to grafana');
res.redirect('http://localhost:8080');
});
request.get('http://localhost:8080',{
auth: {
bearer: 'TOKEN HERE'
}
});
server.listen(4000);
Edited more
app.get('/grafana', isLoggedIn, function(req, res){
console.log('Accessing to grafana');
var url = 'http://localhost:8080/api/dashboards/db/test';
request.get(url,{
auth: {
bearer: 'API token from Grafana page'
}
});
res.redirect(url);
});
Thank you..
The API calls are made with HTTP requests. You can use the request package from npm.
From the docs:
You use the token in all requests in the Authorization header, like this:
GET http://your.grafana.com/api/dashboards/db/mydash HTTP/1.1
Accept: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
Example (I'm using request-promise but you can use whatever you want):
let request = require('request-promise');
let url = `http://your.grafana.com/api/dashboards/db/mydash`;
//Obviously replace this with your token
let myToken = `eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk`;
request.get(url).auth(null, null, true, myToken).then(res=> { ... });
// or
request.get(url, {
auth: {
bearer: myToken
}
}).then(res=> { ... });

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