I am starting with PassportJs/ExpressJs application for authentication
i have two different model for User and Admin
Here is passport.js code
passport.use('admin', new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function(email, password, done) {
var adminflag = 'admin';
console.log('---------------------in admin')
db.adminUser.find({ where: { email: email }}).success(function(user) {
if (!user) {
done(null, false, { message: 'Unknown user' });
} else if (!user.authenticate(password)) {
done(null, false, { message: 'Invalid password'});
} else {
console.log('Login (local) : { id: ' + user.id + ', username: ' + user.username + ' }');
done(null, user);
}
}).error(function(err){
done(err);
});
}
));
LocalStrategy for user
passport.use('user', new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function(email, password, done) {
console.log('---------------------in user')
var userflag = 'user';
db.User.find({ where: { email: email }}).success(function(admin) {
if (!admin) {
done(null, false, { message: 'Unknown user' });
} else if (!admin.authenticate(password)) {
done(null, false, { message: 'Invalid password'});
} else {
console.log('Login (local) : { id: ' + admin.id + ', username: ' + admin.username + ' }');
done(null, admin);
}
}).error(function(err){
done(err);
});
}
));
so My Question is that how can i write serializeUser/deserializeUser for admin and user
passport.serializeUser(function(admin, done) {
if (admin.isSuperAdmin == 0 || admin.isSuperAdmin == 1 ) {
flag = true;
done(null, admin.id);
console.log('----------------------ADMIN');
}else{
flag = false;
console.log('------------------USER');
done(null, admin.id);
};
});
passport.deserializeUser(function(id ,done) {
db.User.find({where: {id: id}}).success(function(admin){
console.log('Session: { id: ' + user.id + ', username: ' + user.username + ' }');
done(null, admin);
}).error(function(err){
done(err, null);
});
});
serializeUser isn't limited to just scalar values, so you can serialize an object that contains the type (admin or plain user):
passport.serializeUser(function(user, done) {
var isAdmin = user.isSuperAdmin === 0 || user.isSuperAdmin === 1;
return done(null, { id : user.id, isAdmin : isAdmin };
});
In your deserialize function, you can check for that type:
passport.deserializeUser(function(user, done) {
var collection = user.isAdmin ? db.adminUser : db.User;
collection.find({ id : user.id }, ...);
});
However, if possible I would consider merging those two collections into one User collection and use a flag to signify if a user is admin or not.
Related
I'm using passport js local strategy for authentication and nodejs. problem is when i try to login with wrong password, I still redirects to success page.
what i have to do
this is login strategy
const passport = require('passport')
const LocalStratery = require('passport-local').Strategy;
const User = require('../models/userAuth')
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local-login', new LocalStratery({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function(req, email, password, done) {
console.log(email)
console.log(password)
User.findOne({email: email})
.then((err, user) => {
if(err) {
return done(null, err, req.flash('unkonown', 'there was an error,
please try after sometime'))
}
if(!user) {
console.log(user)
return done(null, false, req.flash('NotExists', 'no user
exixts'))
}
if(!user.validpass(password)){
return done(null, false, req.flash('passFail', 'password not
matches'))
}
if(user) {
return done(null, user, req.flash('success', 'login success'))
}
})
.catch(err => {
throw err
})
}))
user model using mongoose
userAuth.methods.excryptPass = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(5), null)
}
userAuth.methods.validpass = (password) => {
return bcrypt.compareSync(password, this.password);
}
I'm trying to use a local passport to login and signup in my app.
But when I send a post request from my signup form, the user is being redirected to the signup form.
This is the route definition:
app.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/profile', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
This is my config/passport.js
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
var mysql = require('mysql');
var connection = mysql.createConnection({
host : process.env.MYSQL_HOST,
user : process.env.MYSQL_USER,
password : process.env.MYSQL_PASSWORD,
database : process.env.MYSQL_DB
});
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
console.log("abc serializeUser");
console.log(user);
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log("abc deserializeUser");
User.findById(id).then(function(user){
done(null, user);
}).catch(function(e){
done(e, false);
});
});
passport.use('local-signup', new LocalStrategy(
function(username, password, done) {
console.log("abc local signup");
User.findOne({where: {username: username}}).then(function(err, user) {
if (err) { return done(err); }
if (!user) {
console.log('Incorrect username.');
return done(null, false, { message: 'Incorrect username.' });
} else if (password != user.password) {
console.log('Incorrect password');
return done(null, false, { message: 'Incorrect password.' });
} else {
console.log('ok');
done(null, user);
}
});
}
));
};
This is the models/user.js
"use strict";
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
email: DataTypes.STRING,
password: DataTypes.STRING,
token: DataTypes.STRING
}
);
return User;
};
Sequelize's .then() receives result only, errors should be handled by .catch() block. So the query will looks like this:
User.findOne({where: {username: username}}).then(function(user) {
if (!user) {
console.log('Incorrect username.');
return done(null, false, { message: 'Incorrect username.' });
} else if (password != user.password) {
console.log('Incorrect password');
return done(null, false, { message: 'Incorrect password.' });
} else {
console.log('ok');
done(null, user);
}
}).catch(function(err){
done(err);
});
I am running into an issue where I am trying to access my passport functions from my separate config file, but it doesn't appear that passport is being exposed when I require the file in my routes file. The error is occurring at .post(passportConfig.authenticate('local-login', {
Error:
has no method 'authenticate'
at Object. (/Users/user/Desktop/Projects/node/user-app/app/controllers/site-routes.js:68:23)`
passport.js (Passport authentication logic):
module.exports = function(passport){
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var models = require('../models/db-index');
/*==== Passport Configuration ====*/
// Serialize sessions
passport.serializeUser(function(user, done) {
console.log(user.user_id + "Serializing");
done(null, user.user_id);
});
passport.deserializeUser(function(user_id, done) {
models.User.findById(user_id).then(function(user){
done(null, user);
}).error(function(err){
done(err, null);
});
});
//Login Logic
passport.use('local-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done){
models.User.findOne({ where: { email : email }}).then(function(user) {
if (!user) {
done(null, false, req.flash('loginMessage', 'Unknown User'));
} else if (!user.validPassword(password)) {
done(null, false, req.flash('loginMessage', 'Wrong password'));
} else {
done(null, user);
}
}).catch(function(e) {
done(null, false, req.flash('loginMessage', e.name + " " + e.message));
});
}));
//Sign up Logic
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function(req, email, password, done){
models.User.findOne({ where: { email: email }}).then(function(existingUser){
if (existingUser)
return done(null, false, req.flash('loginMessage', 'That email is already taken.'));
if (req.user) {
var user = req.user;
user.email = email;
user.password = models.User.generateHash(password);
user.save().catch(function (err){
throw err;
}).then(function(){
done(null, user);
});
} else {
var newUser = User.build({
email: email,
password: models.User.generateHash(password)
});
newUser.save().then(function(){ done(null, newUser);
}).catch(function(err){
done(null, false, req.flash('loginMessage', err));
});
}
}).catch(function(e){
done(null, false, req.flash('loginMessage',e.name + " " + e.message));
})
}));
};
site-routes.js:
var express = require('express');
var siteRoutes = express.Router();
var path = require('path');
var passportConfig = require(path.resolve(__dirname, '..', '..','./config/passport.js'));
var models = require('../models/db-index');
/*==== Index ====*/
siteRoutes.get('/', function(req, res){
res.render('pages/index.hbs');
});
siteRoutes.get('/flash', function(req, res){
req.flash('test', 'it worked');
res.redirect('/')
});
/*==== Login ====*/
siteRoutes.route('/login')
.get(function(req, res){
res.render('pages/login.hbs');
})
.post(passportConfig.authenticate('local-login', {
successRedirect: '/app',
failureRedirect: '/login',
failureFlash: 'Invalid username or password.'
}));
siteRoutes.route('/sign-up')
.get(function(req, res){
res.render('pages/sign-up.hbs');
})
.post(function(req, res){
models.User.create({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password
}).then(function() {
res.redirect('/app');
//res.redirect('/sign-up/create-organization');
}).catch(function(error){
res.send(error);
})
});
module.exports = siteRoutes;
When you require config/passport.js, passportConfig will be initialized as a function, as you assigned a function to module.exports in your passport.js file. I'm referring to this line:
module.exports = function(passport){
What I'd do is to get rid of the function. Let the code execute and then assign passport to module.exports. .authenticate method is sitting on passport object.
Like this:
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var models = require('../models/db-index');
/*==== Passport Configuration ====*/
// Serialize sessions
passport.serializeUser(function(user, done) {
console.log(user.user_id + "Serializing");
done(null, user.user_id);
});
passport.deserializeUser(function(user_id, done) {
models.User.findById(user_id).then(function(user){
done(null, user);
}).error(function(err){
done(err, null);
});
});
//Login Logic
passport.use('local-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done){
models.User.findOne({ where: { email : email }}).then(function(user) {
if (!user) {
done(null, false, req.flash('loginMessage', 'Unknown User'));
} else if (!user.validPassword(password)) {
done(null, false, req.flash('loginMessage', 'Wrong password'));
} else {
done(null, user);
}
}).catch(function(e) {
done(null, false, req.flash('loginMessage', e.name + " " + e.message));
});
}));
//Sign up Logic
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function(req, email, password, done){
models.User.findOne({ where: { email: email }}).then(function(existingUser){
if (existingUser)
return done(null, false, req.flash('loginMessage', 'That email is already taken.'));
if (req.user) {
var user = req.user;
user.email = email;
user.password = models.User.generateHash(password);
user.save().catch(function (err){
throw err;
}).then(function(){
done(null, user);
});
} else {
var newUser = User.build({
email: email,
password: models.User.generateHash(password)
});
newUser.save().then(function(){ done(null, newUser);
}).catch(function(err){
done(null, false, req.flash('loginMessage', err));
});
}
}).catch(function(e){
done(null, false, req.flash('loginMessage',e.name + " " + e.message));
})
}));
module.exports = passport;
I want to display error or succuss message during authentication using passport,my code in passport.js is:
var passport = require('passport');
var flash = require('connect-flash');
var LocalStrategy = require('passport-local').Strategy,
User = require(process.cwd() + '/app/models/user');
module.exports = function() {
passport.use(new LocalStrategy({
usernamelocal: 'userid',
passwordlocal: 'password'
},
function(username, password, done) {
User.findOne({
userid: username
}, function(err, user) {
if (err)
return done(err);
if (!user) {
console.log("*************user name error");
this.message = "user error";
return done(null, false, {
message: 'unknown user'
});
}
if (user.deleted) {
console.log("user deleted error");
return done(null, false, {
message: 'unknown user'
});
}
});
}
));
}
Here's the code for a new user:
var User = mongoose.model('User', userSchema);
var usr = new User({ username: 'bob', email: 'bob#example.com', password: 'secret' });
Here's the code for checking login.
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: 'Unknown user ' + username }); }
user.comparePassword(password, function(err, isMatch) {
if (err) return done(err);
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Invalid password' });
}
});
});
}));
If the username doesn't exist, it says "Unknown user __________"
Instead of saying unknown user, I want to create a new user in the database. How do I modify this code to do that?
I'd like to create a new user with the login info they entered if that login name doesn't already exist.
Update
I'm trying this and it's not working. bob5 isn't saving to the database.
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) { usr = new User({ username: 'bob5', email: 'bob5#example.com', password: 'secret' });
usr.save(function(err) {
if(err) {
console.log(err);
} else {
console.log('user: ' + usr.username + " saved.");
}
});
If I type this, bob99 gets saved to the database. So I can create a user... I just need to pass the arguments to it within the if statement (I think).
usr = new User({ username: 'bob99', email: 'bob99#example.com', password: 'secret' });
usr.save(function(err) {
if(err) {
console.log(err);
} else {
console.log('user: ' + usr.username + " saved.");
}
});
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
usr = new User({ username: 'bob99', email: 'bob99#example.com', password: 'secret' });
usr.save(function(err) {
if(err) {
console.log(err);
} else {
console.log('user: ' + usr.username + " saved.");
}
});
}
user.comparePassword(password, function(err, isMatch) {
if (err) return done(err);
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Invalid password' });
}
});
});
}));