login works even if the password incorrect using passportJs - node.js

I am trying to build authentication system for my website , and I am using express to build server , and passport local strategy for authentication ,
let passport = require("passport");
let LocalStrategy = require("passport-local").Strategy;
let session = require("express-session");
app.use(session({ secret: "super secret" }));
app.use(passport.initialize());
app.use(passport.session());
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);
}
return done(null, user);
});
})
);
when I signup , everything works and hashed password save in the database :
app.post("/signup", async (req, res) => {
let { fullname, email, username, password } = req.body;
let user = new User({ fullname, email, username });
await User.register(user, password);
res.redirect("/login");
});
but when I try to login , the user logins if the username is exists regardless the password :
app.post(
"/login",
passport.authenticate("local", {
failureFlash: true,
failureRedirect: "/login",
}),
async (req, res) => {
let user = await User.findById(req.user._id);
if (user.lastLogin === undefined) {
await User.updateOne({ _id: user._id }, { lastLogin: Date.now() });
res.redirect("/final-step");
}
res.redirect("/hi");
}
);
Hope to help me , thanks

I solved the problem by replace this code :
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);
}
return done(null, user);
});
})
);
by :
passport.use(new LocalStrategy(User.authenticate()));

I had the same issue, I solved it by adding
{ strictQuery: false }
in the schema like this:
new Schema({}, {
strictQuery: false
})
after that it was returning correct values

Related

Passport authentication does nothing

I am using passport for authentication. The code doesn't giving any errors but does nothing when I use the right credentials. I tried console log in the authenticateUser function and serializeUser function, it does print statements in both.
My passportConfig.js file
const LocalStrategy = require('passport-local').Strategy;
const db = require('../postgresql');
const bcrypt = require('bcrypt');
function initialize(passport) {
const authenticateUser = async (email, password, done) => {
try {
const user = await db.oneOrNone('SELECT * FROM users WHERE email = $1', [email]);
if(user) {
if(!bcrypt.compareSync(password, user.password)) {
return done(null, false, { message: "Email or password is incorrect"});
}
else {
console.log('Authenticated user');
return done(null, user);
}
}
else {
return done(null, false, { message: "Email or password is incorrect"});
}
}
catch (err) {
console.log(err);
}
}
passport.use(
new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
}, authenticateUser
)
);
passport.serializeUser((user, done) => {
console.log('Serialized user');
done(null, user.id)
});
passport.deserializeUser(async (id, done) => {
try {
const user = await db.oneOrNone('SELECT * FROM users WHERE id = $1', [id]);
return done(null, user);
}
catch(err) {
console.log(err);
}
});
}
module.exports = initialize;
Snippet of my route file
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
}));

Passport error when serialize with another strategy

Create a new type of login for a different type of user (another list in the database), the login succeeds but it doesn't serialize me grow and then show it (just like it does for user). Any idea what it could be ?
Passport Config:
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
var User = require('../model/User')();
var Grow = require('../model/Grow')();
passport.use('local', new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
// Match Email User
const user = await User.findOne({ email: email });
if (!user) {
return done(null, false, { message: 'No se encontro el usuario' });
} else {
// Match Password User
const match = await user.matchPassword(password);
if (match) {
return done(null, user);
} else {
return done(null, false, { message: 'ContraseƱa incorrecta' });
}
}
}));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
passport.use('growlocal', new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
const grow = await Grow.findOne({ email: email });
if (!grow) {
return done(null, false, { message: 'No se encontro el usuario' });
} else {
const match = await grow.matchPassword(password);
if (match) {
return done(null, grow);
} else {
return done(null, false, { message: 'ContraseƱa incorrecta' });
}
}
}));
passport.serializeUser((grow, done) => {
console.log(grow)
done(null, grow.id);
});
passport.deserializeUser((id, done) => {
console.log(grow)
Grow.findById(id, (err, grow) => {
done(err, grow);
});
});
Router Config:
// Login Grow
router.get('/grows/signin', (req, res) => {
res.render('growlogin');
});
router.post('/grows/signin', passport.authenticate('growlocal', {
successRedirect: '/',
failureRedirect: '/grows/signin',
failureFlash: true
}));
EJS:
<% if (grow){ %>
Gato
<%}%>
Error:
If anyone has any idea how to fix it, please let me know. It is very important for the development of my application. Thank you very much <3

Nuxt auth with passportjs?

How use nuxt auth Module (front-end) with passport-local using JWT (back-end express) ?
defining jwt strategy for verify jwt token (express)
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = 'secret';
opts.issuer = 'accounts.examplesoft.com';
opts.audience = 'yoursite.net';
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({id: jwt_payload.sub}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
// or you could create a new account
}
});
}));
defining local strategy for verify username nad password (express)
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); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
code for issuing token after verifying username and password (expresss)
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login' }), //need to update from nuxt auth.
function(req, res) {
res.redirect('/');
});
nuxt auth local strategy consume username and passsword returns a JWT token (nuxt)
this.$auth.loginWith('local', {
data: {
username: 'your_username',
password: 'your_password'
}
})
It can work independently how do i combine these ?
code for express
Create passport strategies
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const JwtStrategy = require('passport-jwt').Strategy;
passport.use(
new LocalStrategy(
{
usernameField: 'username',
passwordField: 'password'
},
function(username, password, done) {
users.findOne({ email: username }, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, { error: 'Invalid username' });
}
if (!user.checkPassword(password)) {
return done(null, false, { error: 'invalid password' });
}
const info = { scope: '*' };
done(null, user, info);
});
}
)
);
const opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = 'JWT_SECRET_OR_KEY';
passport.use(
new JwtStrategy(opts, function(payload, done) {
users.findById(payload, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
}
return done(null, false);
});
})
);
use passport strategies
const express = require('express');
const passport = require('passport');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(passport.initialize()); // Used to initialize passport
// Routes
app.post(
'/login',
passport.authenticate('local', { session: false }),
function(req, res) {
const token = jwt.sign(req.user.userId, 'JWT_SECRET_OR_KEY');
return res.json({ token });
}
);
app.get(
'/me',
passport.authenticate(['jwt', 'bearer'], { session: false }),
function(req, res, next) {
const { userId } = req.user;
users.findOne({ _id: userId }, (err, data) => {
if (err) {
res.status(500).send(err);
} else if (data) {
const userData = data;
res.status(200).send(userData);
} else {
res.status(500).send('invalid token');
}
});
}
);
configuration for nuxt
inside nuxt.config.js
auth: {
resetOnError: true,
redirect: {
login: '/login', // User will be redirected to this path if login is required.
home: '/app/dashboard', // User will be redirect to this path after login. (rewriteRedirects will rewrite this path)
logout: '/login', // User will be redirected to this path if after logout, current route is protected.
user: '/user/profile',
callback: '/callback // User will be redirect to this path by the identity provider after login. (Should match configured Allowed Callback URLs (or similar setting) in your app/client with the identity provider)
},
strategies: {
local: {
endpoints: {
login: {
url: '/login',
method: 'post',
propertyName: 'token'
},
logout: false,
user: {
url: '/me',
method: 'GET',
propertyName: false
}
},
tokenRequired: true,
tokenType: 'Bearer'
}
}
inside Login .vue
this.$auth
.loginWith('local', {
data: {
username: this.user.email,
password: this.user.password
}
})
.catch(err => {
console.error(err );
});

Passport local strategy doesnt return user

My signup and login works completely fine until I want to return user to the front end. User ends up being undefined.
Here is my passport.js
const passport = require('passport');
const localStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const User = mongoose.model('users');
passport.serializeUser((user, done) => {
done(null, user._id)
})
passport.deserializeUser((id, done) =>
User.findById(id).then((user) => {
if (user) {
done(null, user)
} else {
}
})
);
passport.use(new localStrategy((username, password, done) => {
User.findOne({ username: username }, (err, user) => {
console.log(user)
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Username not found' });
}
if (!user.comparePassword(password, user.password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}));
Here is my login route:
const passport = require('passport');
const mongoose = require('mongoose');
const User = mongoose.model('users');
module.exports = (app) => {
app.get('/test', (req, res) => {
res.send('elo')
})
app.post('/login',
passport.authenticate('local', {
successRedirect: '/loginSuccess',
failureRedirect: '/loginFailed',
})
);
app.get('/loginSuccess', (req, res) => {
console.log(req.user)
res.send({ success: true, test:'test', user: req.user })
})
app.get('/loginFailed', (req, res) => {
res.send({ success: false, error: "Incorrect credentials" })
})
};
In passport.js the user exists and should be returnet correctly. It's just getting lost somewhere along the way. Whats funnier, I used the exact same code in my other app few months ago and it worked properly.
Edit:
Turns out it works on postman, so I dont know whats going on now

Passport simple authentification with hashed password on an API

I try to authentificate on a /login route with passport, I give an email, and a password (already stored in the database -email + hashed password with bcrypt). However, when I try to authentificate, my code never go into the passport.use...
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const db = require("../config/database");
/* Route methods */
exports.login = (req, res) => {
const email = req.body.email;
const password = req.body.password;
console.log("It will be displayed");
passport.use(
new LocalStrategy(function(email, password, done) {
console.log("It won't");
db.User.findOne({ email: email }, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, { message: "Incorrect email." });
}
if (!bcrypt.compareSync(password, user.dataValues.password)) {
return done(null, false, { message: "Incorrect password." });
}
return done(null, user);
});
})
);
};
Furthermore, I create an API, and I'm wondering how authentificate someone (with session) with a REST API. Do I have to send on a endpoint the email and the password, then I create a session ? Thank you if you have any ressources.
This happens because you have only declared the actual Strategy but you'll need to create a separate route where you will authenticate the user using this local strategy with passport.authenticate.
Take a look at the example app I've created: https://github.com/BCooperA/express-authentication-starter-api
In config/passport.js I've created the actual Strategy:
const passport = require('passport')
, mongoose = require('mongoose')
, User = mongoose.model('User')
, LocalStrategy = require('passport-local').Strategy;
/**
|--------------------------------------------------------------------------
| Local authentication strategy (email, password)
|--------------------------------------------------------------------------
*/
passport.use(new LocalStrategy({ usernameField: 'user[email]', passwordField: 'user[password]' },
function(email, password, done) {
User.findOne({email: email}, function (err, user) {
if(err)
return done(err);
// incorrect credentials
if (!user || !user.validPassword(password) || user.password === '') {
return done(null, false, { errors: [{ msg: "Incorrect credentials" }] });
}
// inactive account
if(user.activation_token !== '' || user.active === 0) {
// account is not activated
return done(null, false, { errors: [{ msg: "Inactive account" }] });
}
// all good
return done(null, user);
});
}));
In addition, I've also created a separate POST route for signing in users locally where I'm using passport.authenticate.
In routes/auth.routes.js:
const router = require('express').Router()
, mongoose = require('mongoose')
, User = mongoose.model('User')
, passport = require('passport');
/**
|--------------------------------------------------------------------------
| Local Authentication
|--------------------------------------------------------------------------
| Authenticates user using Local Strategy by Passport
*/
router.post('/signin', function(req, res, next) {
if(req.body.user.email === '' || req.body.user.password === '')
// overrides passports own error handler
return res.status(422).json({errors: [{ msg: 'Missing credentials'}]});
passport.authenticate('local', { session: false }, function(err, user, info) {
if(err)
return next(err);
if(user) {
// generate JSON web token to user
user.token = user.generateJWT();
// return user object
return res.status(200).json({ user: user.toAuthJSON() });
} else {
// return any errors
return res.status(422).json(info);
}
})(req, res, next);
});
module.exports = router;

Resources