I am using Passport for logging users in Nodejs. But when I tried to access the user by req.user, I get: Promise { pending }
However, I can get the users id with req.session.passport.user.id - Is it fine to do it that way?
This is the promise, how can I improve it?
const getUserBy = async (what, type) => {
const poolConnection = mysql.createPool({
host : 'localhost',
user : 'root',
password: 'password',
port: 3306,
database: 'mydb'
});
//FIND THE USER AND RETURN IT
return new Promise(function (resolve, reject){
poolConnection.getConnection((err, con) => {
if(err) resolve(false)
con.query("SELECT * FROM thetable WHERE " + type + " = ? LIMIT 1", [what], (err, row) => {
if(err) resolve(false)
//If there were no rows found
if(row.length != 1) resolve(null)
//Resolve the user found
resolve(row[0])
})
})
})
}
/* INITIALIZE PASSPORT TO RETURN */
const initialize = (passport) => {
const authenticateUser = async (email, password, done) => {
const user = await getUserBy(email, "EMAIL")
if(user == false) return done(null, false, {message: "Unable to find this user"});
if(user == null) return done(null, false, {message: "This account and password don't match"});
//Check if the password match the database
const foundPass = await bcrypt.compare(password, user.password);
if(!foundPass) return done(null, false, { message: "This account and password don't match" })
return done(null, user)
}
passport.use(new LocalStratergy({ usernameField: 'email' }, authenticateUser));
passport.serializeUser((user, done) => done(null, user.id))
passport.deserializeUser((id, done) => done(null, getUserBy(id, "ID")))
}
I am not very sure if I should get the user using a promise, but it was the only way I made it work.
Related
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
}));
This is the error I'm getting in passport.js config. I don't understand what it means: Why passport.use is not a function?
TypeError: passport.use is not a function
This is my code:
const LocalStrategy = require('passport-local').Strategy;
const passport = require('passport');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// load user models
const User = require('../models/Users');
module.exports = function (passport) {
passport.use (
new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
// Match User
User.findOne({ email: email })
.then((user) => {
if (!user) {
return done(null, false, { message: 'Email is not registered' })
}
})
.catch((err) => {
console.log(err);
})
// match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw (err)
if (isMatch) {
return done(null, user)
} else {
return done(null, false, { message: 'Incorrect Password' })
}
})
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser( (id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
}
passport.js
const passport = require("passport")
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/user');
// Local Strategy
passport.use(new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
try {
// find the user given the email
const user = await User.findOne({ "email": email });
// if not, handle it
if (!user) {
return done(null, false);
}
// check if password is correct
const isMatch = await user.isValidPassword(password);
// if not handle it
if (!isMatch) {
return done(null, false);
}
// otherwise return the user
done(null, user);
} catch (error) {
done(error, false);
}
}));
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
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 get authentication with Google+ OAuth. To achieve this I'm using passportjs with Google strategy (passport-google-oauth20 module) but I'm stuck in an error while passport tries to serialize the user into a session (using cookie-session).
The error comes after login in the Google site.
The code:
passport.serializeUser((user, done) => {
console.log('serialize ' + (user.id == undefined ? null : user.id));
console.log(user);
return done(null, (user.id == undefined ? null : user.id));
});
passport.deserializeUser((id, done) => {
console.log('dserialize id ' + id);
db.connect((err, client, don) => {
if (err) throw err
client.query('SELECT * FROM "AppUsers" WHERE "googleId" = $1', [id], (err, res) => {
don();
if (err) {
console.log(err.stack);
} else {
console.log(res.rows[0]);
if (res.rows[0]) {return done(null, res.rows[0]);}
else {return done(null, null);}
}
});
});
});
Edit:
async function checkGoogle(profile) {
const client = await db.connect();
try {
const { rows } = await client.query('SELECT * FROM "AppUsers" WHERE "googleId" = $1', [profile.id]);
let currentUser = rows[0];
console.log(currentUser);
if (currentUser) {
console.log('in db ' + currentUser.id);
console.log(currentUser);
return currentUser;
} else {
const { rows } = await client.query('INSERT INTO "AppUsers" ("googleId") VALUES ($1) RETURNING *', [profile.id]);
let newUser = rows[0];
console.log('not in db ' + newUser.id);
console.log(newUser);
return newUser;
}
} catch (error) {
alert(error);
} finally {
client.release();
}
}
passport.use(
new GoogleStrategy({
// options for google strategy
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret,
callbackURL: '/auth/google/redirect'
}, (accessToken, refreshToken, profile, done) => {
// check if user already exists in our own db
return done(null, checkGoogle(profile));
})
);
Output:
The error screen
Please tell me if you need more information about.
You need to wait for the checkGoogle function to return data by using async/await.
passport.use(
new GoogleStrategy({
// options for google strategy
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret,
callbackURL: '/auth/google/redirect'
}, async (accessToken, refreshToken, profile, done) => {
const user = await checkGoogle(profile);
// check if user already exists in our own db
return done(null, user);
})
);