I am very stuck with a routing error on express.js. I am using jade to render my page views. I have read all the docs and refactored many times to no avail.
This is the plain contents of the link that is pointing to the '/sell' route.
index.jade
include layout
html
button.btn.btn-primary(type='submit', href='/sell') Add Item
When clicking this button the browser returns the following as a 404:
Cannot GET /sell
The problem here is that all other routes work correctly, if you are to modify the above href to other pages i.e. '/' , '/sign_in', etc no error occurs. The problem appears to be isolated to the '/sell' route.
The controller with the '/sell' route is below:
server.js
var dotenv = require('dotenv');
dotenv.load();
var session = require('express-session')
var nodemailer = require('nodemailer');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var bcrypt = require('bcrypt');
var async = require('async');
var crypto = require('crypto');
var cookieParser = require('cookie-parser');
var flash = require('express-flash');
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var root = __dirname;
var path = require('path');
var User = require('./models/user');
var bodyParser = require('body-parser');
var errorHelper = require('mongoose-error-helper').errorHelper;
var validator = require('validator');
var Item = require("./models/item")
var username, email, password, owner, product_name, condition, details, price;
mongoose.connect(process.env.MONGODB_CONGO_DEV);
// Middleware
app.set('views', 'app/views');
app.set('view engine', 'jade');
app.set('port', process.env.PORT || 3000);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true}));
app.use(cookieParser());
app.use(session( {
secret: 'session secret key',
resave: false,
saveUninitialized: true
}));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
// Routing
app.get('/', function(req,res) {
res.render('index', {
title: 'Congo',
message: 'Congo',
user: req.user
});
});
app.get('/sell', function(req,res) {
res.render('item', {
title: 'Congo - Sell',
message: 'Sell',
user: req.user
});
});
app.get('/sign_in', function(req,res) {
res.render('sign_in', {
title: 'Congo',
message: 'sign in motherfucker',
user: req.user
});
});
app.post('/sign_in', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) return next(err)
if (!user) {
req.flash('error', 'Incorrect login details');
return res.redirect('/sign_in')
};
req.logIn(user, function(err) {
if (err) return next(err);
res.
return res.redirect('/');
});
})(req, res, next);
});
app.get('/sign_up', function(req, res) {
res.render('sign_up', {
title: 'Congo',
message: 'sign up',
user: req.user
});
});
app.post('/sign_up', function(req, res) {
var user = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password
});
if (req.body.confirm != req.body.password) {
req.flash('error', 'Password do not match')
res.redirect('/sign_up')
};
else if (validator.isEmail(req.body.email) === false) {
req.flash('error', 'Invalid email address')
res.redirect('/sign_up')
};
else {
user.save(function(err) {
if (err) {
req.flash('error', 'Email already in use')
res.redirect('/sign_up')
} else {
req.logIn(user, function(err) {
res.redirect('/');
});
}
});
};
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
app.get('/forgot', function(req, res) {
res.render('forgot', {
user: req.user,
message: 'you wally'
});
});
app.get('/profile', function(req, res) {
res.render('profile', {
user: req.user,
message: 'User profile'
});
});
app.post('/forgot', function(req, res, next) {
async.waterfall([
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
User.findOne({ email: req.body.email }, function(err, user) {
if (!user) {
req.flash('error', 'No account with that email address exists.');
return res.redirect('/forgot');
};
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
user.save(function(err) {
done(err, token, user);
});
});
},
function(token, user, done) {
var smtpTransport = nodemailer.createTransport('SMTP', {
service: 'Gmail',
auth: {
user: 'harryandrew.dix#gmail.com',
pass: process.env.GMAIL_PASS
};
});
var mailOptions = {
to: user.email,
from: 'passwordreset#demo.com',
subject: 'Node.js Password Reset',
text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
'http://' + req.headers.host + '/reset/' + token + '\n\n' +
'If you did not request this, please ignore this email and your password will remain unchanged.\n'
};
smtpTransport.sendMail(mailOptions, function(err) {
req.flash('info', 'An e-mail has been sent to ' + user.email + ' with further instructions.');
done(err, 'done');
});
};
], function(err) {
if (err) return next(err);
res.redirect('/forgot');
});
});
app.get('/reset/:token', function(req,res) {
User.findOne({resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now()}}, function(err,user) {
if (!user) {
req.flash('error', 'Password reset token invalid or expired.');
return res.redirect('/forgot');
}
res.render('reset', {
user: req.user,
message: 'reset dem pass'
});
});
});
app.post('/reset/:token', function(req, res) {
async.waterfall([
function(done) {
User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
if (!user) {
req.flash('error', 'Password reset token is invalid or has expired.');
return res.redirect('back');
};
user.password = req.body.password;
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
user.save(function(err) {
req.logIn(user, function(err) {
done(err, user);
});
});
});
},
function(user, done) {
var smtpTransport = nodemailer.createTransport('SMTP', {
service: 'Gmail',
auth: {
user: 'harryandrew.dix#gmail.com',
pass: process.env.GMAIL_PASS
};
});
var mailOptions = {
to: user.email,
from: 'passwordreset#demo.com',
subject: 'Your password has been changed',
text: 'Hello,\n\n' +
'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n'
};
smtpTransport.sendMail(mailOptions, function(err) {
req.flash('success', 'Success! Your password has been changed.');
done(err);
});
};
], function(err) {
res.redirect('/');
});
});
// app.post('/add_item', function(req, res) {
// var item = new Item({
// owner: req.user.id,
// product_name: req.body.product_name,
// condition: req.body.condition,
// details: req.body.details,
// price: req.body.price
// });
// item.save(function(err) {
// if (err) {
// req.flash('error', 'Something went wrong, make sure you are signed in.')
// res.redirect('/add_item');
// } else {
// req.logIn(item, function(err) {
// res.redirect('/user_profile');
// });
// };
// });
// });
var server = app.listen(3000, function() {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s',host,port);
});
item.jade
include layout
html
block content
form(method='POST')
legend(style='font-family: Raleway; font-size: 30px;') Item Details
.form-group
label(for='product_name') Product Name
input.form-control(type='text', name='product_name', placeholder='include product name, brand, condition, colour etc.', required autofocus)
.form-group
label(for='condition') Condition
input.form-control(type='text', name='condition', placeholder='e.g. New, Used', required)
.form-group
label(for='image') Image
input.form-control(type='file', name='image')
.form-group
label(for='details') Details
textarea.form-control(name='details', cols='40', rows='5')
.form-group
label(for='price') Price
.input-group
.input-group-addon £
input.form-control(type='text', placeholder='Amount', required)
.input-group-addon .00
br
br
button#btnSubmit.btn.btn-primary(type='submit') Post Item
I think it's acting as form post and tries to reach app.post('/sell')
Change it:
button.btn.btn-primary(type='submit', href='/sell') Add Item
to:
a.btn.btn-primary(href='/sell') Add Item
also remove some parts of middleware and keep only these lines:
app.set('views', 'app/views');
app.set('view engine', 'jade');
app.set('port', process.env.PORT || 3000);
app.use(logger('dev'));
and then navigate in Your browser to /sell route, check if it's working.
if Yes - so problem with one of middlewares that we have deleted to check.
You should add a logger middleware and see what error the server gives when you try to go to that route. Another thing to try would be to rename the sell route and see if that works. That could indicate a conflict with another one of your routes, although it's not clear where this would be from looking at your code.
Related
I have tried almost every method known to stack Overflow but my issue is persisting as the days goes by and I'm really hoping for some help here. As you can tell from the title, Passport-local does not call deserializeUser for some odd reason. My files are set up as shown below.
User.js
const express = require('express');
const app = express();
const router = express.Router();
// const db = require('../config/db');
const session = require('express-session');
const SqlDbStore = require('express-mysql-session')(session);
const passport = require('passport');
const bodyParser = require('body-parser');
const crypto = require('crypto');
const cookieParser = require('cookie-parser')
//----------------------------------------- BEGINNING OF PASSPORT MIDDLEWARE AND SETUP ---------------------------------------------------
app.use(session({
key: 'session_cookie_name',
secret: 'session_cookie_secret',
store: new SqlDbStore({
host: 'localhost',
port: 3306,
user: 'xxxxxxxxxx',
password: 'xxxxxxxxx',
database: 'xxxxxxxxxx',
}),
resave: false,
saveUninitialized: false,
cookie:{
maxAge:1000*60*60*24,
secure: false
}
}));
app.use(passport.initialize());
app.use(passport.session());
require('../config/ppc.js')(passport);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
/*passport middleware*/
function genPassword(password) {
var salt=crypto.randomBytes(32).toString('hex');
var genhash=crypto.pbkdf2Sync(password, salt, 10000, 60, 'sha512').toString('hex');
return {salt:salt, hash:genhash}
};
function checkAuthentication(req,res,next){
if(req.isAuthenticated()){
//req.isAuthenticated() will return true if user is logged in
next();
} else{
res.redirect("/login");
}
};
//----------------------------------------- END OF PASSPORT MIDDLEWARE AND SETUP ---------------------------------------------------
router.post('/register', (req, res) => {
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const email = req.body.email;
const saltHash = genPassword(req.body.password);
const salt = saltHash.salt;
const hash = saltHash.hash;
db.query('SELECT * FROM Users WHERE UsersEmail = ? ', [email], (err, results) => {
if (err){
console.log(err)
} else if (results.length > 0) {
res.json({ message: 'Email is already registered!' });
} else {
db.query('INSERT INTO Users (UsersFirstName, UsersLastName, UsersEmail, UsersPasswordHash, UsersPasswordSalt) VALUES (?, ?, ?, ?, ?)', [firstName, lastName, email, hash, salt], (err, results) => {
if (err){
console.log(err);
};
res.send(results);
});
}
})
});
router.post('/login', function(req, res, next){
// console.log(req.body);
passport.authenticate('local', function(err, user){
// console.log('Error: ' + err);
// console.log('User ID: ' + user.id + '\nUser Email: ' + user.email + '\nUser Salt: ' + user.salt + '\nUser Hash: ' + user.hash);
// console.log(err, user);
if(err) {
res.json({message: err.message});
}
if(!user) {
res.json({message: info.message});
}
req.logIn(user, (err) => {
if(err) {
res.json({message: err.message});
} else {
return res.redirect('/');
}
});
})(req, res, next);
});
module.exports = router;
PPC.js
module.exports = function (passport) {
const LocalStrategy = require('passport-local').Strategy;
const db = require('./db');
const crypto = require('crypto');
db.connect((err) => {
if (!err) {
console.log("BD Connected");
} else {
console.log("BD Conection Failed");
console.log(err.message);
res.json({message: err.message})
}
});
const customFields={
usernameField: 'email',
passwordField:'password',
};
/*Passport JS*/
const verifyCallback=(email,password,done)=>{
db.query('SELECT * FROM Users WHERE UsersEmail= ?', [email], function(error, results, fields) {
if (error) {
console.log('query error: ' + error);
return done(error);
}
if(results.length==0) {
return done(null,false, { loggedIn: false, message: 'Account is not recognized.'});
}
const isValid=validPassword(password, results[0].UsersPasswordHash, results[0].UsersPasswordSalt);
user={id:results[0].UsersID, email:results[0].UsersEmail, hash:results[0].UsersPasswordHash, salt:results[0].UsersPasswordSalt};
if(isValid) {
return done(null,user, { loggedIn: true, email: email});
} else{
return done(null,false, { loggedIn: false, message: 'Password is incorrect.'});
}
});
};
const strategy = new LocalStrategy(customFields, verifyCallback);
passport.use(strategy);
passport.serializeUser((user,done)=>{
console.log('Inside serialize');
done(null, user.id);
});
passport.deserializeUser((userId, done) => {
console.log('Inside deserialize');
db.query('SELECT * FROM Users WHERE UsersID = ?', [userId], function(error, results) {
done(null, results[0]);
});
});
function validPassword(password, hash, salt){
const hashVerify=crypto.pbkdf2Sync(password, salt, 10000, 60, 'sha512').toString("hex");
return hash === hashVerify;
};
}
I am totally unsure as to what I did wrong here. One thing I will say is, when I change all app.use() to router.use() in my User.Js, I got a consider upgrading MySQL error when I am using mysql2. Regardless, I don't think mysql is my issue because I am able to register to the DB fine using mysql2 and app.use. I believe my issue most likely lies in the router.post(/login).
I ended up just moving to my own encryption method which uses bcrypt. It was the easiest and securest way to go about this process especially with out wasting to much time. If I ever find the solution in the future, I’ll post it on GitHub and will post the link here.
More information on Bcrypt.
I've been following a guide on implementing a password reset in Node. I'm working on the password reset post route below and when I post nothing seems to happen, it justs reloads the reset page. ive added some console.log() in various places on the code but they dont get executed. Hope someone can assist. ive deleted the other routes to make the code shorter
var express = require('express');
var router = express.Router({ mergeParams: true });
var Kids = require('../models/kid');
var User = require('../models/user');
var async = require('async');
var nodemailer = require('nodemailer');
var crypto = require('crypto');
var middleware = require('../middleware');
//password reset
router.get('/password_reset', function (req, res) {
res.render('password_reset');
});
//posting the account email reset
router.post('/password_reset', function (req, res, next) {
async.waterfall([
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
User.findOne({ email: req.body.email }, function(err, user) {
if (!user) {
req.flash('error', 'No account with that email address exists.');
return res.redirect('/forgot');
}
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
user.save(function(err) {
done(err, token, user);
});
});
},
function(token, user, done) {
var smtpTransport = nodemailer.createTransport('SMTP', {
service: 'SendGrid',
auth: {
user: 'Hidden',
pass: 'Hidden'
}
});
var mailOptions = {
to: user.email,
from: 'passwordreset#demo.com',
subject: 'Node.js Password Reset',
text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
'http://' + req.headers.host + '/reset/' + token + '\n\n' +
'If you did not request this, please ignore this email and your password will remain unchanged.\n'
};
smtpTransport.sendMail(mailOptions, function(err) {
req.flash('info', 'An e-mail has been sent to ' + user.email + ' with further instructions.');
done(err, 'done');
});
}
], function(err) {
if (err) return next(err);
res.redirect('/forgot_reset');
});
});
module.exports = router;
i figured out the issue, it was to do with my form. I had forgotten to add:
<form method="post" action="/password_reset">
so the form was not sending anything.
I am trying to create an api for login in nodejs.but when i check the login route via Http requester it showing nothing in output and command line showing error Error: Uncaught, unspecified "error" event. (Not a valid BCrypt hash.) and i find out that password is not stored in database in encrypted/hash form.
The project structure:
server.js file:
var express = require('express');
var app = express();
var port = process.env.PORT||8080;
var morgan = require('morgan');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var router = express.Router();
var appRoutes = require('./app/routes/api')(router);
var path = require('path');
app.use(morgan('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
app.use('/api',appRoutes);
mongoose.connect('mongodb://localhost:27017/tutorial', function(err){
if(err) {
console.log('Not connected to the Database: '+ err);
}
else {
console.log('Succesfully connected to Mongodb');
}
});
app.get('*',function(req,res){
res.sendFile(path.join(__dirname + '/public/app/views/index.html'));
});
app.listen(port, function () {
console.log('Running the server on port ' + port);
});
/app/models/user.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
var UserSchema = new Schema({
username: { type: String, lowercase: true, required: true, unique: true },
password: { type: String, required: true },
email: { type: String, lowercase: true, required: true, unique: true }
});
UserSchema.pre('save', function(next) {
var user = this;
bcrypt.hash(user.password, null, null, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
next();
});
UserSchema.methods.comparePassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
module.exports = mongoose.model('User', UserSchema);
/app/routes/api.js:
var User =require('../models/user');
module.exports = function(router) {
//http://localhost:8080/api/users
//User Registration Route
router.post('/users', function(req,res){
var user = new User();
user.username = req.body.username;
user.password = req.body.password;
user.email = req.body.email;
if (req.body.username == null || req.body.username == '' || req.body.email == null || req.body.email == ''|| req.body.password == null || req.body.password == '' ){
res.send('Ensure Username, Email and Password is provided');
} else {
user.save(function(err){
if(err){
res.send('Username or Email already exist');
}
else {
res.send('User created!!!')
}
});
}
});
//User login Route
//http://localhost:8080/api/authenticate
router.post('/authenticate',function(req,res) {
User.findOne({ username: req.body.username }).select('email username password').exec(function(err,user){
if (err) throw err;
if (!user){
res.json({ success: false, message: 'Could not authenticate user'});
}else if(user){
var validPassword = user.comparePassword(req.body.password);
if(!validPassword){
res.json({ success: false, message: 'Could not authenticate user'});
}else {
res.json({ success: true, message: 'User Authenticate!!!'});
}
}
});
});
return router;
}
HTTP requester (it is working fine for register api in /app/models/api.js){and user is succesfully registered}
Terminal:
Database:(where password is not stored in hash i dont know why maybe this is main problem)
Your code calls next() twice in your pre-save function, remove it as followed:
UserSchema.pre('save', function(next) {
var user = this;
bcrypt.hash(user.password, null, null, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
next(); // function to remove
});
I'm going crazy with nodejs. I'm trying to realize the backend for a simple user management webapp powered by NodeJS, using Passport-Local and Sequelize libraries. Right now I just designed the user model. The main problem I have is that the signup process gives me an error: it looks like that I'm working on an undefined object. Could please someone help me in figuring out what's going on?
Here is my code (merged with some solutions I found on internet - obviously nothing works, according to Murphy's laws).
Could please Javascript programmers forgive me if the code is not good. My excuse is that it is my first programming attempt in Javascript, I MUST do it for a project and last (excuse) but not least I grew up with C and microchips.
ERROR:
TypeError: Cannot read property 'findOne' of undefined
at Strategy._verify (/home/me/Documents/cerbero/config/passport.js:21:17)
app.js
var app = express();
//blabla favicon stuff
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({ secret:'holaholaholaholaholaholahola',
resave:true,
saveUninitialized:true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
var models = require("./models")
require('./config/passport.js')(passport, models.usermodel);
app.use('/', index);
app.use('/user', require('./routes/users')(passport));
models.sequelize.sync().then(function(){
console.log("Database connected");
}).catch(function(err) {
console.log(err, "Somenthing went wrong with the dbdbdb");
});
//blabla listening stuff
module.exports = app;
models/usermodel.js
module.exports = function(sequelize, Sequelize) {
var User = sequelize.define('user', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
username: {
type: Sequelize.TEXT
},
public_key: {
type: Sequelize.TEXT
},
email: {
type: Sequelize.STRING,
validate: {
isEmail: true
}
},
password: {
type: Sequelize.STRING,
allowNull: false
},
last_login: {
type: Sequelize.DATE
},
});
return User;
}
routes/users.js
var express = require('express');
module.exports = function(passport, user) {
var router = express.Router();
//blablabla other routes
router.get('/signup', function(req,res,next) {
res.render('signup', {message: req.flash('signupMessage')});
});
router.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/user/dashboard',
failureRedirect: '/user/signup'}
));
router.post('/login', passport.authenticate('local'), function(req, res) {
res.redirect('/');
});
return router;
};
function isLogged(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
};
EDIT
I forgot passport strategy.
passport.js
var bCrypt = require('bcrypt-nodejs');
module.exports = function(passport, user) {
var User = user;
var LocalStrategy = require('passport-local').Strategy;
console.log('debug: sono nella routine');
passport.use('local-signup', new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done) {
User.findOne({
where: {
email: email
}
}).then(function(user) {
if (user) {
return done(null, false, {message: req.flash('email already taken')});
console.log('mail already taken');
}
else {
var pass = generateHash(password);
var data =
{
email: email,
password: pass,
username: req.body.username,
public_key: '0',
last_login: null
};
User.create(data).then(function(newUser, created) {
if (!newUser) {
return done(null, false);
}
if (newUser) {
return done(null, newUser, {message: req.flash('tappost')});
}
next();
});
}
});
}
));
passport.deserializeUser(function(id, done) {
User.findById(id).then(function(user) {
if (user) {
done(null, user.get());
} else {
done(user.errors, null);
}
});
});
passport.serializeUser(function(user,done) {
done(null, user.id);
});
var generateHash = function(password) {
return bCrypt.hashSync(password, bCrypt.genSaltSync(8), null);
};
Problem solved.
"Just" changed how to reference the model in passport.js as follow
var User = user;
had to rewritten as
var User = db.user;
Here the definitive passport strategy file
const db = require('./../models/');
var bCrypt = require('bcrypt-nodejs');
module.exports = function(passport) {
var User = db.user;
var LocalStrategy = require('passport-local').Strategy;
passport.use('local-signup', new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done) {
var generateHash = function(password) {
return bCrypt.hashSync(password, bCrypt.genSaltSync(8), null);
};
User.findOne({
where: {
email: email
}
}).then(function(user) {
if (user) {
return done(null, false, {message: req.flash('email already taken')});
console.log('mail already taken');
}
else {
var pass = generateHash(password);
var data =
{
email: email,
password: pass,
username: req.body.username,
public_key: '0',
last_login: null
};
User.create(data).then(function(newUser, created) {
if (!newUser) {
return done(null, false);
}
if (newUser) {
return done(null, newUser, {message: req.flash('tappost')});
}
});
}
}).catch(function(err) {
console.log(err);
});
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id).then(function(user){
done(null, user);
}).catch(function(e){
done(e, false);
});
});
}
I set-up passport on nodejs with mongoose for allowing users to login and create new accounts. Create new account is working but the login part doesn't.
users.js
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongoose = require('mongoose');
var User = require('../models/user');
router.get('/login', function(req, res, next) {
res.render('login', {
'title': 'Login'
});
});
passport.serializeUser(function(user, done){done(null, user);});
passport.deserializeUser(function(id, done){
User.getUserById(id, function(err, user){
done(err, user);
});
});
passport.use(new LocalStrategy(
function(username, password, done){
User.getUserByUsername(username, function(err, user){
if(err) throw err;
if(!user){
console.log('Unknown 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{
console.log('Invalid Password');
return done(null, false, {message: 'Invalid password'});
}
});
});
}
));
router.post('/login', passport.authenticate('local', {successRedirect: '/',failureRedirect: '/users/register', failureFlash:'Invalid username or password'}), function(req,res){
console.log('Authentication Successful');
req.flash('success', 'You are logged in');
res.redirect('/');
});
../models/user.js
var mongoose = require('mongoose');
var bcrypt = require('bcrypt');
mongoose.connect('mongodb://localhost/nodeauth');
var db = mongoose.connection;
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true
},
password: {
type: String, required: true, bcrypt: true
},
email:{
type: String
},
name:{
type: String
},
profileimage:{
type: String
}
});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch){
if(err) return callback(err);
callback(null,isMatch);
});
}
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
}
module.exports.createUser = function(newUser, callback){
bcrypt.hash(newUser.password, 10, function(err, hash){
if(err) throw err;
// Set hashed pw
newUser.password = hash;
// Create User
newUser.save(callback);
});
}
If I create the new user than is working the data are uploading the MongoDB but if I try to Log In it just drop me to the /users/register page I do not have any error
Well it is not doing anything because your login route is not calling anything... check the documentation on http://passportjs.org/docs to see how passport works.
In user.js you need something like
router.get('/login',
passport.authenticate('local'),
function(req, res) {
res.render('login', {
'title': 'Login'
});
});
Then in a separate file you need to setup your authentication strategy, for example:
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
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);
});
}
));
Check this tutorial for a step-by-step on implementing local authentication strategy.
http://code.tutsplus.com/tutorials/authenticating-nodejs-applications-with-passport--cms-21619
If you want something more advanced, this code has examples of social authentication strategies (for example, your users can log in using Facebook accounts)
https://github.com/mjhea0/passport-examples
Good luck!