I begin with express and pasport. I use MVC structure for my project.
in controller auth.js
members.authMember(username, password, function() {
console.log('HERE')
});
and in member_model.js
var passport = require('passport')
var LocalStrategy = require('passport-local').Strategy;
exports.authMember = function authMember(username, password, callback) {
db.openConnection();
passport.use(new LocalStrategy( function(username, password, done) {
Members.find({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
// callback('Incorrect username.');
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
// callback('Incorrect password.');
return done(null, true, { message: 'Incorrect password' });
}
// callback(user);
return done(null, user);
});
}));
callback();
db.closeConnection();
}
After submit username and password using authMember function, my app does not response.
And commit to :
https://github.com/ryantranvn/start
My problem is authorization with link :
http://localhost:3000/admin/login
Thanks advances!
PS: username of member in DB is : admin
Related
I have a simple login form that I created. It seems to authenticate any existing user as long as the password field has something in it. Obviously, it is a huge security flaw. I'm new to mean stack and using passport to authenticate users seemed easy but not sure if I did it wrong.
This is my backend code using passportjs:
app.js
const passport = require('passport');
require('./config/passport');
app.use(passport.initialize());
routes/index.js
const ctrlAuth = require('../controllers/authentication');
router.post('/login', ctrlAuth.login);
controllers/authentication.js
module.exports.login = function(req, res) {
passport.authenticate('local', function(err, user, info){
let token;
// If Passport throws/catches an error
if (err) {
res.status(404).json(err);
return;
}
// If a user is found
if(user){
token = user.generateJwt();
res.status(200);
res.json({
"token" : token
});
} else {
// If user is not found
res.status(401).json(info);
}
})(req, res);
};
And finally, my config file
config/passport.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const User = mongoose.model('User');
passport.use(new LocalStrategy({
usernameField: 'email'
},
function(username, password, done) {
User.findOne({
email: username
}, function(err, user) {
if (err) {
return done(err);
}
//Return if user not found in database
if (!user) {
return done(null, false, {
message: 'User not found'
});
}
//Return if password is wrong
if (!user.validPassword(password)) {
return done(null, false, {
message: 'Password is wrong'
});
}
//If credentials are correct, return the user object
return done(null, user);
});
}
));
I believe I've narrowed the bug down to my validPassword function where I might be using bcrypt incorrectly.
userSchema.methods.validPassword = function(password){
return bcrypt.compare(password, this.hash);
};
I narrowed my issue down to my validPassword method and found that I was using bcrypt incorrectly. Changed it to
userSchema.methods.validPassword = function(password){
return bcrypt.compareSync(password, this.hash);
};
Makes more sense after looking at the docs for bcrypt https://github.com/kelektiv/node.bcrypt.js#readme
I know this question was asked many times in stack over flow. I tried every accepted answers but can't my local strategy into function. Here is my code
var express = require('express');
var app = express();
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
app.set('trust proxy', 1); // trust first proxy
app.use(session({
secret: '564sdf4as564f56a7s765s4afjkgadxjkbadksj',
resave: true,
saveUninitialized: true,
cookie: { secure: true }
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy({
usernameField:'userName',
passwordField:'password',
passReqToCallback : true
},function(request, userName, password, done) {
console.log(request);
UserAccount.findOne({'userName': userName} , function(err, user) {
if (err) return done(err);
if (!user) return done(null, false, 'Incorrect username.' );
user.verifyPassword(password, function(err, isMatch) {
if (isMatch) {
return done(null, user);
} else {
return done(null, false, 'Incorrect password.');
}
});
});
}));
passport.serializeUser(function(user, done) {
console.log('Serialize user called');
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log('Deserialize user called');
UserAccount.findById(id, function(err, user) {
done(err, user);
});
});
Then I created a router like
var router = express.Router();
require('./controllers/user')(router,passport);
app.use('/api',router);
Then in my user controller I created signIn function like
app.post('/signIn',function (request,response,next){
var variables = request.body;
console.log(variables);
passport.authenticate('local', function(error, user, info) {
console.log(user);
if (error) { console.log(error); return next(err); }
if (!user) { return response.redirect('/login'); }
response.logIn(user, function(err) {
if (err) { return next(err); }
return response.redirect('/users/' + user.username);
});
})(request, response, next);
});
Then I send a request from "Postman"
{
"userName":"karthik#abc.com",
"password":"qwerty"
}
My mongodb userName and password fields are same.
In my db there is an account with this user name and password. But every time it return 'user' as 'false' inside authenticate. I tried to console my request inside local strategy but it never gets called. I don't understand What I done wrong here? Can some one help to solve this? Thank you very much.
You should name local strategy and use it in authenticate.
Use like this passport.use('local-strategy',new LocalStrategy({});
and like passport.authenticate('local-strategy');
after successful register with passport in express, when i try to login. it failed and i don't know which code is causing error. please help.
here is my code.
router.post('/register',function(req,res){
//fetch user info
var firstName=req.body.firstName,
lastName = req.body.lastName,
mobile= req.body.mobile,
email = req.body.email,
password = req.body.password,
newsConsent = req.body.newsConsent;
var userInfo = {firstName: firstName, lastName: lastName, mobile: mobile, email:email, newsConsent: newsConsent };
//register and create user
User.register(new User(userInfo), password, function(error, userCreated)
{
if (error)
{
console.log(error);
// req.flash("error", error.message);
return res.render("auth/register");
}
else
{
req.login(userCreated, function(err) {
if (err) {
console.log(err);
return next(err);
}
console.log(userCreated);
return res.redirect('/');
});
}
});
});
//login route
router.post("/login", passport.authenticate("local",
{
successRedirect: "/",
failureRedirect: "/register"
}), function(req, res){
console.log(req.body);
});
also please tell me how to know about the error in passport
You need declare your strategy, serialize and deserialize. Here's my code. You can edit it as you need. FYI, I was using 'nip_nim' instead of 'username', so I set "usernameField" as nip_nim. Here I also use 'flash' package to save my notification data.
passport.use(new LocalStrategy({
usernameField: 'nip_nim',
passReqToCallback: true
}, function (req, nip_nim, password, done) {
var params = {
nip_nim: nip_nim
}
var user = new User_Model(params);
user.getDataUserByNIPorNIM()
.then(function (result) {
if (!helper.isExist(nip_nim) || !helper.isExist(password)) {
return done(null, false, req.flash('message_err', 'NIM/NIM dan password tidak boleh kosong.'));
}
if (!result) {
return done(null, false, req.flash('message_err', 'NIP/NIM yang anda masukkan salah.'));
}
if (!bcrypt.compareSync(password, result.password)) {
return done(null, false, req.flash('message_err', 'Password yang anda masukkan salah.'));
}
return done(null, result);
})
}));
//serialize and deserialize passport
passport.deserializeUser(function (nip_nim, done) {
var params = {
nip_nim: nip_nim
}
var user = new User_Model(params);
user.getDataUserByNIPorNIM()
.then(function (result) {
done(null, result);
})
});
passport.serializeUser(function (req, user, done) {
done(null, user.nip_nim, req.flash('message_success', 'Welcome, ' + user.nama_unit_org + "."));
});
ok. i found the culprit. it's not passport, it's mongoose schema.
i have to add {index : true} in username.
`username : {type:String, unique: true, index: true},`.
after that everything works fine.
In the signup process, I avoided the missing credentials with adding (see just below) while saving the user
newUser.firstName = req.body.firstName;
newUser.lastName = req.body.lastName;
But now when logging in I get the same error "missing credentials". Last time I added it while saving the user in the signup process but now I'm just loggin in...
What am I missing?
var passport = require('passport');
var User = require('../models/user');
var LocalStrategy = require('passport-local').Strategy;
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('local.signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function(req, email, password, done) {
req.checkBody('email', 'Invalid email').notEmpty().isEmail();
req.checkBody('password', 'Invalid password').notEmpty().isLength({min: 6});
var errors = req.validationErrors();
if (errors) {
var messages = [];
errors.forEach(function(error) {
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({
'email': email
}, function(err, user) {
if (err) {
return done(err);
}
if (user) {
return done(null, false, {message: 'Email is already in use.'});
}
var newUser = new User();
newUser.firstName = req.body.firstName;
newUser.lastName = req.body.lastName;
newUser.email = email;
newUser.password = newUser.encryptPassword(password);
newUser.save(function(err, result) {
if (err) {
return done(err);
}
return done(null, newUser);
});
});
}));
passport.use('local.login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function(req, email, password, done) {
req.checkBody('email', 'Invalid email').notEmpty().isEmail();
req.checkBody('password', 'Invalid password').notEmpty();
var errors = req.validationErrors();
if (errors) {
var messages = [];
errors.forEach(function(error) {
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({
'email': email
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, {message: 'No user found.'});
}
if (!user.validPassword(password)) {
return done(null, false, {message: 'Wrong password.'});
}
return done(null, user);
});
}));
Ok, figured it out... The problem was in the view. Had forgotten to include id and name on the signin form like I had in the signup form...
I want to use req.flash("message" : error ) to support error message callbacks for passportJS inside of SailsJS. However, PassportJS does not handle the below during callbacks: (similar post: PassportJS Custom Authenticate Callback Not Called)
//there is no req found
req.flash("message" , "invalid password");
This usually will be alright if there's something like:
function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
//....
req.flash("message" , "invalid password");
}
But I can't use it inside passport.use.
/services/passport.js
passport.use(new HttpBasicStrategy(
function(username, password, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
// Find the user by username. If there is no user with the given
// username, or the password is not correct, set the user to `false` to
// indicate failure. Otherwise, return the authenticated `user`.
findByUsername(username, function(err, user) {
if (err)
return done(null, err);
if (!user) {
return done(null, false, {
message: 'Unknown user ' + username
});
}
bcrypt.compare(password, user.password, function (err, res) {
if (!res){
--> //there is no req found
--> req.flash("message" , "invalid password");
return done(null, false, {
message: 'Invalid Password'
});
}
var returnUser = {
username: user.username,
createdAt: user.createdAt,
id: user.id
};
return done(null, returnUser, {
message: 'Logged In Successfully'
});
});
})
});
}
));
Is there another way to call req.flash? I'm pretty new at express and sailsjs, please pardon my ignorance.
For sails v0.10.x sails-generate-auth is perfect for this.