i am newbie in sails and i was making a simple login functionality in which the controller named find is going to db and checking if the user name password is valid or not, but the problem i am facing is it's checking for the user name and i think not for the password because in the param i am passing the correct password, i am passing param through using link simply, the link through which i am passing param is
http://localhost:1337/find/index?name=ahsan&pass=pakistan
and the code in my find controller is
var Sequelize = require('sequelize');
var sequelize = require('../../config/config_db').dbase;
var user = sequelize.define('Data',{
username: Sequelize.STRING,
birthday: Sequelize.STRING
})
sequelize.sync();
module.exports = {
index: function (req, res) {
var n = req.param('name');
var p = req.param('pass');
user.find({ where: { username : n, password : p } })
.complete(function(err, name, pass)
{
if (!!err)
{
return res.json('error while connecting db')
}
else if (!name)
{
return res.json('no user with this name')
}
else if (!pass)
{
return res.json('no user with this password')
}
else
{
return res.json('user is valid')
};
})
// Send a JSON response
// return res.json({
// hello: 'world'
},
_config: {}
};
and the query executing in console is
SELECT * FROM `Data` WHERE `Data`.`username`='ahsan' AND `Data`.`password`='pakistan' LIMIT1;
Tthe password pakistan exist in my db and the out it's showing me is
"no user with this password"
please let me know if i am mistaking.
You're misusing the .complete() callback in Sequelize. It should have two parameters: err and the retrieved item (in this case a user). Try:
user.find({ where: { username : n, password : p } })
.complete(function(err, user)
{
if (!!err)
{
return res.json('error while connecting db')
}
else if (!user.name)
{
return res.json('no user with this name')
}
else if (!user.pass)
{
return res.json('no user with this password')
}
else
{
return res.json('user is valid')
};
});
Related
Am trying to login my admin , i defined the login credentials both in the mongodb and in the .env so here is the code which has a problem.
const Admin = require('../models/admin');
const Voters = require('../models/voters');
const bcrypt = require('bcrypt');
exports.checkCredentials = async (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
Admin.findOne({ email: email }).exec(async (error, adminData) => {
if (error) {
// some error occured
return res.status(400).json({ error });
}
if (adminData) {
// email is correct checking for password
const match = await bcrypt.compare(password, adminData.password);
if (match) {
req.adminID = adminData._id;
next();
} else {
return res.status(200).json({
msg: 'Invalid email/password combination yyy',
});
}
} else {
// no data found for given email
return res.status(200).json({
msg: 'Invalid email/password combination !!!!',
});
}
});
};
exports.verifyVoter = async (req, res, next) => {
let query;
if (req.query.voterID) {
query = {
voterID: req.query.voterID,
};
} else {
query = {
phone: req.body.phone,
};
}
console.log(query);
Voters.findOne(query).exec(async (error, voterData) => {
if (error) {
// some error occured
return res.status(400).json({ error });
}
if (voterData) {
// Voter found
if (voterData.hasRegistered === true) {
return res.status(200).json({
msg: 'Voter already registered',
});
} else {
req.phone = voterData.phone;
req.district = voterData.pinCode;
req._id = voterData._id;
next();
}
} else {
// no data found for given Voter
return res.status(200).json({
msg: 'Invalid VoterID',
});
}
});
};
that code above brings an error but this is how i defined my admin credentials in the .env
ADMIN_EMAIL = bkroland19#gmail.com
ADMIN_PASSWORD =felinho/013
and this is how i defined them in mongodb
{
"email": "bkroland19#gmail.com",
"password": "felinho/013"
}
and this is the resulting error i get yet the email am entering matches those two emails.
Any help please
Am expecting to be allowed to login in when i enter the credentials as they are in the mongodb database
If you store the password in cleartext you don't need bcrypt.compare:
const match = password === adminData.password;
if (match) {
req.adminID = adminData._id;
next();
}
Anyway, it is strongly suggested to encrypt it, you can do it with:
const salt = await bcrypt.genSalt(12);
const encryptedPassword = await bcrypt.hash(password, salt);
const user = await Admin.create({ email, password: encryptedPassword });
User registers with a bcrypt hashed password. After proceding with email verification through mailtrap/nodemailer and successfully verifing user status to true, the login fails, returning 'unmatched password", because it is changing stored user hashed password. If I skip the verification step and proceed with login directly, it will work fine. So how do I do 'user verification' without changing stored hashed password in my code below?
async login(req: Request, res: Response){
// Get user from database
const userRepository = getRepository(User);
const { email, password } = req.body;
if (!(email && password)) {
console.error('Empty name or password!');
return res.status(400).send({
error: 'Empty name or password'
});
}
const user = await userRepository.findOne({ where: { email } });
let storedUserPass = user!.password;
console.log(password) //-> consoles plain typed text
console.log(storedUserPass) //-> consoles encrypted password
const isValidPassword = await bcrypt.compareSync(password, storedUserPass as string);
console.log(isValidPassword) //-> consoles false
if(!user) {
return res.send(`User doesn t exist! `);
}
else if (!user.isVerified) {
return res.send('Your Email has not been verified. Please do so!');
}
else if(!isValidPassword) {
return res.send('Password doesn t match')
}
else {
// Sing JWT, valid for 1 hour
const token = jwt.sign(
{ id: user.id, email: user.email },
process.env.NODE_ENV,
{ expiresIn: "1d" }
);
res.json({
user,
token
});
}
},
async create(req: Request, res: Response) {
const verificationToken = await crypto.randomBytes(8).toString('hex');
const { name, email, password, role, isVerified } = req.body;
const date = new Date();
try {
const userRepository = getRepository(User);
const tokenRepository = getRepository(Token);
//User validation
const data = {
name,
email,
password,
}
const schema = Yup.object().shape({
name: Yup.string().required('Name required.').max(60),
email: Yup.string().email("Invalid Email.").required(),
password: Yup.string().required().min(4).max(10),
})
await schema.validate(data, {
abortEarly: false
});
const userExists = await userRepository.findOne({ where: { email }})
if(userExists) {
return res.send(`Usuário com email cadastrado ${email} já existe!` );
} else {
const token = tokenRepository.create({token: verificationToken, tokenDate: date})
await tokenRepository.save(token);
const user = userRepository.create({ name, email, password, role: role || "basic", isVerified, date, token})
console.log(user.password) // consoles plain text
await userRepository.save(user);
console.log(user.password) //consoles encrypted text
return new Promise((resolve,reject)=>{
const transp = transport;
var mailOptions = {
from: 'Administrador <c3e26a9df0-703049#inbox.mailtrap.io>',
to: email,
subject: 'Account verification link!',
html: `<h2>Olá ${user.name}</h2><br/>
<p>Finalize o seu cadastro clicando neste <a href="http://${req.headers.host}/users/confirmation/${user.email}/${verificationToken}" target="_about" style="color: blue, text-derocation: none"}>Link</a>`
}
transp.sendMail(mailOptions, function(error: Err){
if (error) {
return res.status(500).send({msg:'Technical Issue!,Please click on resend for verify your Email.'});
}
else {
return res.send('A verification email has been sent to ' + user.email + '. It will be expire after one day. If you not get verification Email click on resend token.');
});
})
}
} catch(err) {
return res.status(404).send({ err: "Failed to send email."})
}
},
//TYPEORM USER MODEL:
#Entity('users')
export default class User {
#PrimaryGeneratedColumn('uuid')
id: number;
#Column()
name: string;
#Column({
unique: true
})
email: string;
#Column()
password: string;
#Column()
role: string;
default: 'basic'
enum: ["basic", "supervisor", "admin"];
#Column({
type: "datetime"
})
date!: Date;
#Column({
default: false
})
isVerified: boolean;
#BeforeInsert()
#BeforeUpdate()
hashPassword() {
this.password = bcrypt.hashSync(this.password, 8); // salt de 8
}
checkIfUnencryptedPasswordIsValid(unencryptedPassword: string) {
return bcrypt.compareSync(unencryptedPassword, this.password);
}
#OneToMany(() => Orphanage, orphanage => orphanage.user, {
cascade: ['insert' , 'update']
})
#JoinColumn({ name: 'user_id'})
orphanages: Orphanage[];
#OneToOne(type => Token)
#JoinColumn()
token: Token;
}
async confirmEmail(req: Request, res: Response) {
try {
const userRepository = getRepository(User);
const tokenRepository = getRepository(Token);
const tokenExists = await tokenRepository.findOne({ token: req.params.token });
tokenExists!.tokenDate
if( !tokenExists ) {
return res.status(400).send({msg:'Your verification link may have expired. Please click on resend for verify your Email.'});
} else {
const user = await userRepository.findOne({where: { token: tokenExists, email: req.params.email }})
//user not exist
if(!user) {
return res.status(401).send({msg:'We were unable to find a user for this verification. Please SignUp!'});
} // user is already verified
else if (user.isVerified){
return res.status(200).send('User has been already verified. Please Login');
} else { //verify user
user.isVerified = true;
await userRepository.save(user);
console.log(user) // -> hashed user.password is different from when created user after user is verified.
return res.status(200).send('Your account has been successfully verified')
}
}
} catch(err) {
return res.status(500).send({err: "Sorry, it could not be validated!"});
}
},
Using ? in user?.password is not a valid way. The symbol? is used in the ternary operator. The ternary operator needs three parameters and you are not providing these parameters.
solution: format your code as given below. I used the ! operator in user!.password. This operator in user! ensures your transpiler that the user will not be undefined. So, before using this operator you should check whether a user is defined or not, in this way:
if(!user) {
return res.send(`User doesn t exist! `);
}
If you don't check the user before using ! you may get a run-time error in the case of an undefined user. No need to use as string.
Changed Block in your code:
const user = await userRepository.findOne({ where: { email } });
//check user immediately after getting it to avoid errors
if(!user) {
return res.send(`User doesn t exist! `);
}
let storedUserPass = user!.password;
const isValidPassword = await bcrypt.compareSync(password, storedUserPass);
Now your code will look like:
async login(req: Request, res: Response){
// Get user from database
const userRepository = getRepository(User);
const { email, password } = req.body;
if (!(email && password)) {
console.error('Empty name or password!');
return res.status(400).send({
error: 'Empty name or password'
});
}
const user = await userRepository.findOne({ where: { email } });
if(!user) {
return res.send(`User doesn t exist! `);
}
let storedUserPass = user!.password;
const isValidPassword = await bcrypt.compareSync(password, storedUserPass);
if (!user.isVerified) {
return res.send('Your Email has not been verified. Please do so!');
}
else if(!isValidPassword) {
return res.send('Password doesn t match')
}
else {
// Sing JWT, valid for 1 hour
const token = jwt.sign(
{ id: user.id, email: user.email },
process.env.NODE_ENV,
{ expiresIn: "1d" }
);
res.json({
user,
token
});
}
}
Shakir Aqeel, please do not consider my last answer, I got confused, the prob has nothing to do with token.
But I have always used same library to encrypt the password when creating user, located on User model:
hashPassword() {
this.password = bcrypt.hashSync(this.password, 8);
}
In the User controller:
console.log(user.password) -> plain typed password
await userRepository.save(user);
console.log(user.password) -> encrypted password
If I register a new user with verification status as 'true', it will login with no problem....
I'm trying to create a basic register/sign up web app with Express, Vue.js and MongoDB.
I have written some backend validation such as checking the all the fields are filled in and the passwords match etc... and then push a string of the error message into an array if the user fails the validation.
If a user tries to sign up on the front end and fails some part of the validation the user is not inserted into the database but to message is displayed as to why and that what I'm having trouble with.
router.post("/register", (req, res) => {
const name = req.body.name;
const email = req.body.email;
const password = req.body.password;
const password2 = req.body.password2;
let errors = [];
// check required fields
if (!name || !email || !password || !password2) {
errors.push({ msg: "please fill in all fields" });
}
// check for errors
if (password !== password2) {
errors.push({ msg: "Passwords do not match" });
}
// password validation
if (password.length < 6) {
errors.push({ msg: "Password to short" });
}
if (errors.length > 0) {
// if there are errors redirect
res.redirect("/");
console.log(errors);
} else {
// res.send("pass");
// check if the user already exists:
User.findOne({ email: email }).then(user => {
if (user) {
// User exists
// if you have found one user
// then user exists and send to home page
errors.push({ msg: "Email is already registered" });
res.redirect("/");
console.log(errors);
} else {
// create new user by using the keyword 'new'
// name is equal to const name = req.body.name; etc...
const newUser = new User({
name: name,
email: email,
password: password
});
console.log(newUser + " hi new user");
// Hash Password before insert into db
bcrypt.genSalt(10, (err, salt) =>
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
// set PS to hashed PS
newUser.password = hash;
// save user
// insert into db then redirect to login
newUser
.save()
.then(user => {
res.redirect("/login");
})
.catch(err => {
console.log(err);
});
})
);
}
});
}
});
Vue:
name: "RegisterForm",
// data is a function that
// returns an object
data: () => ({
errorMessage: "",
user: {
name: "",
email: "",
password: "",
password2: ""
}
}),
// watch allows you to run a function
// any time data changes
watch: {
user: {
handler() {
this.errorMessage;
},
// deep means anytime data changes this watch will run
deep: true
}
},
methods: {
register() {
// clear error message on register
this.errorMessage = "";
// use keyword 'this' to refer to the current object 'methods'
if (this.validUser()) {
// send data to server
axios({
method: "post",
url: "http://localhost:4000/register",
data: {
name: this.user.name,
email: this.user.email,
password: this.user.password,
password2: this.user.password2
}
})
.then(response => {
console.error(response)
})
.catch(error => {
console.error(error)
});
}
},
validUser() {
// if (this.user.password !== this.user.password2) {
// this.errorMessage = "Passwords must match";
// return false;
// } else {
return true;
// }
// }
}
}
};
There is some frontend validation that works (by doing this.errorMessage = "Passwords must match or some error";) and shows a message but I need to show the errors from "let errors = []"
At the moment I'm currently getting a 'ReferenceError: error is not defined' error in the console when typing in invalid data such as two none matching passwords.
Use express-flash-message for save those on redirect. This plugins also expose a local variable for render those message. See documentation.
I am having trouble making the #PUT method for my application. So far, I managed to make the #GET, #POST and #DELETE. So after doing some research, it turns out that the #PUT is a mixture of my #GET and #POST.
My #GET (by cuid) method
export function getUser(req, res) {
// just get the user information
User.findOne({ cuid: req.params.cuid }).exec((err, user) => {
if (err) {
return res.status(500).send(err);
}
return res.json({ user });
});
}
My #POST method
export function addUser(req, res) {
// Check for empty fields
if (!req.body.user.firstName || !req.body.user.lastName ||
!req.body.user.email || !req.body.user.password ||
!req.body.user.studentId) {
return res.status(403).end();
}
const newUser = new User(req.body.user);
// Let's sanitize inputs
newUser.firstName = sanitizeHtml(newUser.firstName);
newUser.lastName = sanitizeHtml(newUser.lastName);
newUser.studentId = sanitizeHtml(newUser.studentId);
newUser.email = sanitizeHtml(newUser.email);
newUser.password = sha512(newUser.password).toString('hex');
newUser.cuid = cuid();
newUser.save((err, saved) => {
if (err) {
return res.status(500).send(err);
}
return res.json({ user: saved });
});
}
The req.body.user will be the same in the #PUT method as in the addUser function on the #POST. In other words, the req.body.user will be something like { firstname: 'assa', lastName: 'nen', email: 'ed#aid.com', password: 'ddee', student: 112 }
My question is how would you modify the specific user (by cuid) information and save it to the db? In other words, how would you write the #PUT method
Try findOneAndUpdate
export function updateUser(req, res) {
var userId = req.body.userId;
var conditions = {
_id : userId
}
var update = {
firstName = sanitizeHtml(req.body.firstName );
lastName = sanitizeHtml(req.body.lastName);
studentId = sanitizeHtml(req.body.studentId);
email = sanitizeHtml(req.body.email);
password = sha512(req.body.password).toString('hex');
}
model.findOneAndUpdate(conditions,update,function(error,result){
if(error){
// handle error
}else{
console.log(result);
}
});
}
I am trying to implement a authentication system for my website using MEAN however I have run into a relatively strange problem. I am able to register users and duplicate usernames can be identified. However, I cannot get logging into the website working. When I search the mongo database using the command line, I do not get anything. This is what my mongo output looks like.
>> show users
>>
The database has the username somewhere... so how do I get the users to be properly displayed? Why is that user is undefined when I try to log in even though I know the username is in the database?
var crypto = require('crypto');
var mongoose = require('mongoose');
var User = mongoose.model('User');
function hashPW(pwd) {
return crypto.createHash('sha256').update(pwd).digest('base64').toString();
};
module.exports.signup = function (req,res) {
var user = new User({username:req.body.usernmae});
console.log('made it here');
user.set('hashed_password', hashPW(req.body.password));
user.set('email', req.body.email);
user.save(function (err) {
if (err) {
try {
if (err.code==11000) res.render('signup', {message: 'Sorry, someone has that username already.'})
} catch(e) {
}
console.log(err);
//res.redirect('/signup');
} else {
req.session.user = user.id;
req.session.username = user.username;
req.session.msg = 'Authenticated as ' + user.username;
res.redirect('/');
}
});
};
module.exports.login = function (req,res) {
User.findOne({ username: req.body.username })
.exec(function(err,user) {
console.log(user);
console.log(err);
console.log(hashPW(req.body.password.toString()));
if (!user) {
err = 'User Not Found.';
} else if ( user.password === hashPW( req.body.password.toString() ) ) {
req.session.regenerate(function() {
req.session.user = user.id;
req.session.username = user.username;
req.session.msg = 'Authenticated as ' + user.username;
res.redirect('/');
});
} else {
err = 'Authentication failed.';
}
if (err) {
console.log(err);
req.session.regenerate(function() {
req.session.msg = err;
res.redirect('/login');
});
}
});
};
I notice that there's a typo in the provided code.
var user = new User({username:req.body.usernmae});
Should likely read
var user = new User({username:req.body.username});
This probably meant the name failed to set thus putting a junk user into your DB.
Also, regarding your command in the Mongo Shell, Neil's answer covered that the show command is not actually useful here. The reference for db.collection.find() is here.
silly mistake. the field is not password but hashed_password.
{ email: 'somerandomemail#gmail.com',
hashed_password: 'A8ctR3JAA84DWTmYXEAhxEEP1bTtAidaoyWArKHtk2g=',
username: 'Szpok',
_id: 54c09c458c4eccc90b9c4bb5,
__v: 0 }