I want to build an application with login and register. Register works fine, but login not (it gives me 501-not implemented error). Here is a snippet from my code:
const passport = require('passport')
router.post('/register', (req, res) => {
knex
.from('user')
.insert({
firstname: req.body.firstname,
lastname: req.body.lastname,
email: req.body.email,
password: req.body.password,
})
.then(() => {
res.json({ success: true, message: "Data successfully inserted." })
})
.catch(() => {
res.json({ success: false, message: "Error in adding user. Please try again." })
})
})
router.post('/login', function (req, res, next) {
passport.authenticate('local', function (err, user, info) {
console.log("1 err " + JSON.stringify(err))
console.log("2 user " + JSON.stringify(user))
console.log("3 info " + JSON.stringify(info))
if (err) { return res.status(501).json(err); }
if (!user) { return res.status(501).json(info); }
req.logIn(user, function (err) {
if (err) { return res.status(501).json(err); }
return res.status(200).json({ message: 'Login Success' });
});
})(req, res, next);
});
When I try to login, I get:
1 err [{"id":1,"firstname":"john","lastname":"doe","email":"jdoe#example.com","password":"joe"}]
2 user undefined
3 info undefined
Why is user undefined? I was expecting to get a true/false value. And also why does err has that value? Because of that, it will always enter on if(err).
I can provide more from my code, if u ask to. Thank you!
EDIT: localpassport
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const knex = require('./db.js');
passport.use('local', new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function (username, password, done) {
knex('user')
.where('email', '=', username)
.then((err, user) => {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.isValid(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
})
}
));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
knex.from('user').where('id', '=', id)
.then((user) => { done(null, user); })
.catch((err) => { done(err, null); });
});
module.exports = passport;
The problem was inside localpassport:
passport.use('local', new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function (username, password, done) {
knex('users')
.where('email', '=', username)
.then((user) => {
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (password != user[0].password) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user[0]);
})
}
));
There was no attribute such err.
Related
I am making register/login page using nodejs but when it comes to the step it returns json when accessing the database as well as when creating a new database
here is my code
register.js
const bcrypt = require("bcryptjs");
const User = require("../model/user");
const register = async (req, res) => {
const {
username,
password: plainTextPassword,
password_confirmation: someOtherPlaintextPassword,
tel_or_email,
} = req.body;
if (!username || typeof username !== "string") {
return res.json({ status: "error", error: "Invalid username" });
}
if (!plainTextPassword || typeof someOtherPlaintextPassword !== "string") {
return res.json({ status: "error", error: "Invalid password" });
}
User.findOne({ Email: tel_or_email }, async (error, user) => {
if (error) throw error;
if (user) {
console.log(user);
return res.json({
status: "ok",
success: "email is already in use, please enter another email",
});
} else {
const password = await bcrypt.hash(plainTextPassword, 10);
const password_confirmation = await bcrypt.hash(
someOtherPlaintextPassword,
10
);
const user = new User({
Name: username,
Email: tel_or_email,
Password: password,
});
user.save((error, result) => {
if (error) throw error;
console.log(result);
});
return res.json({ status: "ok", success: "user successfully created" });
}
});
};
module.exports = register;
status work in the first return ( return res.json({ status: 'error', error: 'Invalid username'}) )and the second( return res.json({ status: 'error', error: 'Invalid password'}) ) , remaining is not
Node how to manage user roles? I want to redirect user to admin or coach dashboard when (is_admin & is_coach) is true in user table? login code is below?
I had used Nodejs for Backend and Reactjs for Frontend and for database i had used Mysql
(here is my signin code )
exports.signIn = (req, res) => {
const reqData = req.body;
checkAccountExistence(reqData)
.then((userDetails) => {
if (userDetails.length > 0) {
checkUserActivation(userDetails[0])
.then((activeUser) => {
if (activeUser.length == 1) {
bcrypt.compare(
reqData.password.toString(),
userDetails[0].password,
(error, response) => {
if (response) {
var token = jwt.sign(
{ id: userDetails[0].id },
config.secret,
{
expiresIn: 86400,
}
);
res.cookie("userToken", token, { maxAge: 86400000 });
res.send({ loginSuccess: true });
} else {
res.send({ invalidMessage: "Invalid Email or Password" });
}
}
);
} else {
const emailData = userDetails[0];
const randnum = Math.random().toString(25).substring(2, 20);
updateActivationCode(userDetails[0], randnum)
.then((response) => {
if (response == 1) {
emailData.randnum = randnum;
emailData.firstname = emailData.first_name;
emailData.template = "accountVerification.ejs";
generateEmail(emailData)
.then((html) => {
emailData.html = html;
const emailOptions = {
from: '"Tester" testmail#zoho.com',
to: emailData.email,
subject: "Account verification",
html: emailData.html,
};
sendMail(emailOptions);
res.send({
verifyMessage:
"Please check your mail to verify your account first",
});
})
.catch((error) => {
res.send(error);
});
}
})
.catch((error) => {
console.log(error);
});
}
})
.catch((err) => {
console.log(err);
});
} else {
res.send({ invalidMessage: "Invalid Email or Password" });
}
})
.catch((error) => {
res.status(422).send({
error: error.errors.map((err) => {
return {
attribute: err.path,
type: err.type,
message: err.message,
};
}),
});
});
};
No matter what I change the user login will keep redirecting to failure instead of success. I don't know if I'm missing something or if I did something wrong. I tried to read the documentation for passport but, I found it pretty confusing. Here is my github link if you need to see the rest of the code. The node files are in app.js and passport-config.js.The sign up part of the website is working. https://github.com/gego144/to-do-list-website/tree/main
const customFields = {
usernameField: 'email',
passwordField: 'password'
}
const verifyCallback = (username, password, done) => {
user_exists = userName_Checker(username), function (err, user) {
if (err) { return done(err); }
if (userName_Checker(username) == false) {
console.log('wrong user');
return done(null, false, { message: 'Incorrect username.' });
}
if (password_finder(username, password)) {
console.log('wrong pass');
return done(null, false, { message: 'Incorrect password.' });
}
console.log('wtf');
return done(null, user);
};
;
}
const strategy = new LocalStrategy(customFields, verifyCallback);
passport.use(strategy);
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// function that checks to see if the users email is in the database
function userName_Checker(email_name){
var sql = "select * from info where email = ?";
var user_email = [[email_name]];
db.query(sql, [user_email],function (err,result){
if (err) throw err;
var not_unique = result.length;
if(not_unique == 0){
return false;
}
else{
return true;
}
}
)}
// function that checks to see if the password in the database matches with the email
function password_finder(email_name, pass){
var sql = "SELECT password FROM info WHERE email = ?";
var user_email = [[email_name]];
db.query(sql, [user_email],function (err,result){
if (err) throw err;
bcrypt.compare(result, pass, function(err, res){
if(err){ throw err};
if(res){
return true;
}
else{
return false;
}
})
}
)}
My post method in my other file.
app.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect:'/index.html',
failureFlash: true
}))
Edit 1.
I just want to mention that the console.logs you see in verify Callback all don't log anything for some reason too.
The problem might be in the serialization logic.
In passport.serializeUser, you are passing in the whole user object, but when deserializing you are passing the id
Though I am not using SQL, the logic should be similar.
So the code should be something like this:
// Session
// Pass in user id => keep the session data small
passport.serializeUser((id, done) => {
done(null, id);
});
// Deserialize when needed by querying the DB for full user details
passport.deserializeUser(async (id, done) => {
try {
const user = await User_DB.findById(id);
done(null, user);
} catch (err) {
console.error(`Error Deserializing User: ${id}: ${err}`);
}
});
// Export the passport module
module.exports = (passport) => {
passport.use(new LocalStrategy({ usernameField: 'email', }, async (email, password, done) => {
try {
// Lookup the user
const userData = await User_DB.findOne({ email: email, }, {
password: 1, }); // Return the password hash only instead of the whole user object
// If the user does not exist
if (!userData) {
return done(null, false);
}
// Hash the password and compare it to the hash in the database
const passMatch = await bcrypt.compare(password, userData.password);
// If the password hash does not match
if (!passMatch) {
return done(null, false);
}
// Otherwise return the user id
return done(null, userData.id);
} catch (err) {
passLog.error(`Login Error: ${err}`);
}
}));
};
These options for passport seems to malfunction a lot or exhibit weird behaviors, so I suggest you handle the redirection logic like in my controller.
{ successRedirect: '/good',
failureRedirect: '/bad' }
Login controller logic:
(I am omitting the code here for session storage and made some modifications, but this code should work for what you need)
const login = (req, res, next) => {
//Using passport-local
passport.authenticate('local', async (err, user) => {
//If user object does not exist => login failed
if (!user) { return res.redirect('/unauthorized'); }
//If all good, log the dude in
req.logIn(user, (err) => {
if (err) { return res.status(401).json({ msg: 'Login Error', }); }
// Send response to the frontend
return res.redirect('/good');
});
});
})(req, res, next);
};
The actual route:
// Import the controller
const {login} = require('../controllers/auth');
// Use it in the route
router.post('/auth/login', login);
I build a simple web application where the user has notes. I want the user to be able to sign in with a google account as well, but the user didn't save into the database. The local login works but the social login doesn't. Wherever I searched I only found a solution in which mongodb was used. What is the correct way with mysql?
Here is my passport.js file:
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((req, user, done) => {
conn.query("SELECT * FROM user WHERE id = ? OR facebook_id = ? OR google_id", [user.id,
user.facebook_id, user.google_id], (err, rows) => {
if (err) {
console.log(err);
return done(null, err);
}
done(null, user);
});
});
passport.use(new GoogleStrategy({
clientID: configAuth.googleAuth.clientID,
clientSecret: configAuth.googleAuth.clientSecret,
callbackURL: configAuth.googleAuth.callbackURL,
passReqToCallback: true,
profileFields: configAuth.googleAuth.profileFields
},
function (req, accessToken, refreshToken, profile, done) {
process.nextTick(function () {
conn.query("SELECT * FROM user WHERE google_id = ?", [profile.id], (err, user) => {
if (err) {
return done(err);
} else if (user) {
return done(null, user);
} else {
let newUser = {
google_id: profile.id,
google_token: accessToken,
google_email: profile.emails[0].value,
google_name: profle.name.givenName + ' ' + profile.name.familyName
};
conn.query("INSERT INTO user (google_id, google_token, google_email, google_name) VALUES (?, ?, ?, ?)",
[newUser.google_id, newUser.google_token, newUser.google_email, newUser.google_name], (err, rows) => {
if (err) {
console.log(err);
}
return done(null, newUser);
})
}
});
});
}
));
And here are the routes:
app.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
app.get('/auth/google/callback', passport.authenticate('google', {
successRedirect: '/main',
failureRedirect: '/'
}));
I can log in, I didn't receive an error message, but if I want to assign a new note to the user it doesn't add it because it doesn't save the user to the database.
I think you forget to put ? after the google_id.
Example:
google_id=?
The console.log("After Function") is executed but console.log("getUserByUsername is called") is not executed and the page remains reloading and NO error log is given, this problems happens to me in many cases and I can't find the reason why.
const Coach = require('./src/models/coache');
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'},
(email, password, done) => {
console.log("After Function");
Coach.getUserByUsername(email, (err, user) => {
console.log("getUserByUsername is called");
});
})
);
here is the Coach.getUserByUsername function:
module.exports.getUserByUsername = (email, callback) => {
CoachesModel.findOne({
where: {email: email}
}, callback);
}
here is the whole program:
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'},
(email, password, done) => {
console.log("After Function");
Coach.getUserByUsername(email, (err, user) => {
console.log("getUserByUsername is called");
if (err) throw err;
if (!user) {
return done(null, false, { message: 'Unknown User' });
}
Coach.comparePassword(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Invalid password' });
}
});
});
})
);
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
Coach.getUserById(id, function (err, user) {
done(err, user);
});
});
app.post('/login',
passport.authenticate('local', { successRedirect: '/profile', failureRedirect: '/users/login', failureFlash: true}),
function (req, res) {
res.redirect('/profile');
});