stuck on 400 bad request, method might be incorrect? - vue.js

Hello im currentenly stuck and im not quite sure whats wrong
my postman login is all fine but my backend dont accept anything so im pretty sure there is something wrong with my method
export default {
data() {
return {
loading: false,
error: null,
login: {
email: "",
password: "",
}
}
},
methods: {
UserLogin: function() {
this.loading = true;
this.axios.post('http://localhost:3000/login', {user: this.login})
.then((res) =>{
this.$cookies.set('jwt', res.data.jwt);
this.$cookies.set('isAdmin', res.data.isAdmin);
this.$router.push('/dashboard');
}).catch(err => {
//fejl
this.error = err.response.data.message;
});
this.loading = false;
},
CheckForNullInObject: function(obj) {
for (let key in obj) {
if(obj[key] == null || obj[key] == "") return false;
}
return true;
}
}
and my backend
router.post('/', async (req, res) => {
if(!req.body.email || !req.body.password) {
res.status(400).json({
message: "missing values1"
});
return
}
always hits the missing values1 no matter what I write

You've POSTed the login data under user, but your backend code doesn't read that property.
Either update your frontend to send the data directly (without user):
this.axios.post('http://localhost:3000/login', { ...this.login })
Or update the backend to read the data from user:
if(!req.body.user.email || !req.body.user.password)

Related

NodeJS: bcrypt is returning false even when the password is correct

I am having trouble with the bcrypt.compare portion of my code. My route is able to hash the password and store the password in the database. The database is able to store 255 characters and I have verified that the password is 60 characters long. Every time I compare the password to the hashed password on the db, I get a false returned on from bycrypt.compare.
Has anyone encountered this and know what I may be doing wrong?
Auth Route for creating the user in the database:
app.post('/register/local', async (req, res) => {
const hashedPassword = await bcrypt.hash(req.body.password, 10) || undefined
const existingLocalUser = await db.User.findOne({ where: { email: req.body.email } }) || undefined
if (!existingLocalUser) {
try {
const newUser = await db.User.create({
given_name: req.body.given_name,
family_name: req.body.family_name,
email: req.body.email,
password: hashedPassword,
}
)
res.redirect('/login')
} catch {
res.redirect('/register')
}
} else if (existingLocalUser.dataValues.google_id) {
const updateUser = await db.User.update(
{ password: hashedPassword },
{ where: { email: req.body.email } }
)
} else {
console.log("You already have an account. Please login.")
res.redirect('/login');
}
})
Local Strategy from Passport:
passport.use(new LocalStrategy( async (username, password, done) => {
const existingLocalUser = await User.findOne({ where: { email: username }})
if (!existingLocalUser) {
console.log("No user exisits")
return done(null, false)
}
console.log("password", password)
console.log("existingLocalUser.password", existingLocalUser.password)
await bcrypt.compare(password, existingLocalUser.dataValues.password, function(error, result) {
if (error) {
return done(error)
} else if (result) {
return done(null, existingLocalUser)
} else {
return done(null, false)
}
})
}
));
bcrypt.compare(password, existingLocalUser.password, function(error, result) {
if (error) {
return done(error)
} else if (result) {
return done(null, existingLocalUser)
} else {
return done(null, false)
}
})
You are trying to use callback and await together, kindly remove await and stick to callbacks or you refactor and use async-await alone
As #cristos rightly pointed out the problem could be that you are mixing up async/await and callbacks. Stick to one pattern.
Here's how your code would be with async/await,
try {
const result = await bcrypt.compare(password, existingLocalUser.password);
if (result) {
return done(null, existingLocalUser);
} else {
return done(null, false);
}
} catch (error) {
return done(error);
}
Also on another note, are you sure you are comparing the correct values?
Going by the code sample you have provided I can see that you are logging,
console.log("password", password)
console.log("existingLocalUser.password", existingLocalUser.password)
However, the values compared in bcrypt.compare() is different,
bcrypt.compare(password, existingLocalUser.dataValues.password)
I figured out why it wasn't working... React or Redux was masking the password with asterisks so changing it to a sting of asterisks which gets hashed..

Two custom methods/endpoints using loopBack, one works, the other gives a 401

I created two custom endpoints with Loopback.
Account.deleteAllHearingTests = function (req, callback) {
console.log('here comes the req to delete all hearing tests', req);
Account.findById(req.accessToken.userId)
.then(account => {
if (!account) {
throw new Error('cannot find user');
}
return app.models.HearingTest.updateAll({ accountId: account.id }, { isDeleted: new Date() });
})
.then(() => {
callback(null);
})
.catch(error => {
callback(error);
})
}
Account.remoteMethod(
'deleteAllHearingTests', {
http: {
path: '/clearHearingTests',
verb: 'post'
},
accepts: [
{ arg: 'req', type: 'object', http: { source: 'req' } }
],
returns: {}
}
);
the second one looks like this.
Account.deleteSingleHearingTest = function (req, callback) {
// console.log('accounts.js: deleteSingleHearingTest: are we being reached????', req)
Account.findById(req.accessToken.userId)
.then(account => {
if (!account) {
throw new Error('Cannot find user');
}
console.log('account.js: deleteSingleHearingTest: req.body.hearingTestId N: ', req.body.hearingTestId);
return app.models.HearingTest.updateAll({ accountId: account.id, id: req.body.hearingTestId }, { isDeleted: new Date() });
})
.then(() => {
callback(null);
})
.catch(error => {
callback(error);
});
}
Account.remoteMethod(
'deleteSingleHearingTest', {
http: {
path: '/deleteSingleHearingTest',
verb: 'post'
},
accepts: [
{ arg: 'req', type: 'object', description: 'removes a single hearing test', http: { source: 'req' } }
],
description: 'this is the end point for a single delete',
returns: {}
}
);
};
The first custom method returns a 401 status response when I make the initial fetch. The second returns a 200.
Inside my actions file the first method is called with something that looks like this:
export function deleteAllHearingTests() {
return (dispatch, getState) => {
let state = getState();
if (!state.user || !state.user.accessToken || !state.user.accessToken.id || !state.user.accessToken.userId) {
console.debug('deleteAllHearingTests', state.user);
// TODO: ERROR
return;
}
fetch(SERVERCONFIG.BASEURL + '/api/Accounts/clearHearingTests?access_token=' + state.user.accessToken.id, {
method: 'POST',
headers: SERVERCONFIG.HEADERS
})
.then(response => {
console.log('here is your response', response);
if (response.status !== 200) {
throw new Error('Something is wrong');
}
return response.json()
})
the second method is called with
export const deleteSingleHearingTest = (hearingTestNumber) => {
return (dispatch, getState) => {
let state = getState();
if (!state.user || !state.user.accessToken || !state.user.accessToken.id || !state.user.accessToken.userId) {
console.debug('writeTestResult', state.user);
// TODO: ERROR
return;
}
console.log('single delete ', SERVERCONFIG.BASEURL + '/api/Accounts/deleteSingleHearingTest?access_token=' + state.user.accessToken.id)
fetch(SERVERCONFIG.BASEURL + '/api/Accounts/deleteSingleHearingTest?access_token=' + state.user.accessToken.id, {
method: 'POST',
headers: SERVERCONFIG.HEADERS,
body: JSON.stringify({ "hearingTestId": hearingTestNumber })
})
.then(response => {
console.log('getting response from initial fetch inside deleteSingleReqport', response);
They are nearly identical, however, one works..the other fails. What are some possible causes for the 401?
Did you try to call those methods with external tool like a postman, so you would exactly know if you don't miss access_token or something else? Also, when you compare code from one function and another, you can see that you are colling the updateAll with different arguments. It's hard to say without original code, but maybe the issue is there? Compare below:
return app.models.HearingTest.updateAll(
{ accountId: account.id },
{ isDeleted: new Date() });
return app.models.HearingTest.updateAll(
{ accountId: account.id, id: req.body.hearingTestId },
{ isDeleted: new Date() });
Additionally, in fetch method they are also diffferences, you are missing in one case the below:
body: JSON.stringify({ "hearingTestId": hearingTestNumber })
What you could also do to debug and to provide more data is to run server in debug mode by calling:
export DEBUG=*; npm start

Bcrypt + Sequelize password not saving as hash in DB

Sequelize + Bcrypt not storing passwords in DB as hash
As the title says, whenever I attempt to store a user into my SQLite DB the console outputs the password as a hash but when I look into the DB with DBbrowser I can see the plaintext password.
Model
// const Promise = require('bluebird')
const bcrypt = require('bcrypt')
async function hashPassword (user, options) {
if (!user.changed('password')) {
return 0
}
const SALT_FACTOR = 8
await bcrypt.hash(user.password, SALT_FACTOR, (err, hash) => {
if (err) {
console.log(err)
}
// user.setDataValue('password', hash)
user.password = hash
console.log(user)
})
}
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
}, {
hooks: {
beforeSave: hashPassword,
beforeCreate: hashPassword
}
})
User.prototype.comparePassword = function (password) {
bcrypt.compare(password, this.password, function (res, err) {
if (res) {
console.log(res)
} else {
console.log(err)
}
})
return bcrypt.compare(password, this.password)
}
return User
}
Controllers
module.exports = {
async register (req, res) {
try {
const user = await User.create(req.body)
const userJson = user.toJSON()
res.send({
user: userJson,
token: jwtSignUser(userJson)
})
} catch (err) {
// e-mail already exists or such
res.status(400).send({
error: 'This email address is already in use'
})
}
},
async login (req, res) {
try {
// Grab user input
const { email, password } = req.body
const user = await User.findOne({
where: {
email: email
}
})
// Check to see if user is in db
if (!user) {
res.status(403).send({
error: 'the login information was incorrect / Not Found'
})
}
// Check to see if password is valid
const isPasswordValid = await user.comparePassword(password)
if (!isPasswordValid) {
return res.status(403).send({
error: 'The login information was incorrect'
})
}
// return user using toJSON()
const userJson = user.toJSON()
res.send({
user: userJson,
token: jwtSignUser(userJson)
})
} catch (e) {
res.status(500).send({ error: 'An error occured attempting to login' })
console.log(e)
}
}
}
To elaborate a little more, whenever I create a user, I receive the following:
{
"user": {
"id": 1,
"email": 'test#test.com",
"password": "$2b$08$SYYXU/GDSCFsp3MVeuqrduI0lOLHeeub7whXiaMMoVxO53YJry.1i",
"updatedAt": "2018-09-07T22:44:12.944Z",
"createdAt": "2018-09-07T22:44:12.944Z"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJTVVBCUkhVQGxvbC5jb20iLCJwYXNzd29yZCI6IiQyYiQwOCRTWVlYVS9HRFNDRnNwM01WZXVxcmR1STBsT0xIZWV1Yjd3aFhpYU1Nb1Z4TzUzWUpyeS4xaSIsInVwZGF0ZWRBdCI6IjIwMTgtMDktMDdUMjI6NDQ6MTIuOTQ0WiIsImNyZWF0ZWRBdCI6IjIwMTgtMDktMDdUMjI6NDQ6MTIuOTQ0WiIsImlhdCI6MTUzNjM2MDI1MywiZXhwIjoxNTM2OTY1MDUzfQ.mDaeIikzUcV_AGTuklnLucx9mVyeScGpMym1y0kJnsg"
}
Which to me says the DB successfully hashed my password, and stored it. The overhanging issue for me with this is the fact that I believe it's causing the bcrypt.compare function to spit out 'false'. As always, any insight or help would be greatly appreciated!
I'm pretty sure that this answer is too late for you, but might help others landing on this same question.
The main issue I can see is how you are using the async/await pattern. Changing this:
async function hashPassword (user, options) {
if (!user.changed('password')) {
return 0
}
const SALT_FACTOR = 8
await bcrypt.hash(user.password, SALT_FACTOR, (err, hash) => {
if (err) {
console.log(err)
}
// user.setDataValue('password', hash)
user.password = hash
console.log(user)
})
}
to this, worked for me:
async function hashPassword(user, options) {
if (!user.changed("password")) {
return 0;
}
user.password = await bcrypt.hash(user.password, SALT_FACTOR);
}
Can you please try to add only one hook
hooks: {
beforeSave: hashPassword,
}
Because I think your password is getting hashed two times. as beforeSave and beforeCreate both hooks get executed.
Hope it helps

Vuevalidate async validation results to a loop

Am using Vue Validate
i have the following in my vuevlidate
validations: {
user_form: {
email: {required,email, isUnique(value) {
// standalone validator ideally should not assume a field is required
if (value === '') return true;
// simulate async call, fail for all logins with even length
return new Promise((resolve, reject) => {
this.$http.post("v1/user-management/users/email-registeredi",{email:value}).then((res)=>{
console.log("res is ", res);
resolve(true);
},(err)=>{
reject(false)
})
})
}},
role: {required},
password: {required}
}
},
The above creates an endless loop of http requests especially when it gets an error
Where am i going wrong
In case vue validate is not handling reject promise well and creating infinite loop.
You can try, async await for Vue validate's isUnique with try and catch returning false on error,
something like this.
validations: {
user_form: {
email: {
required,
email,
async isUnique (value) {
if (value === '') return true
try{
const response = await this.$http.post("v1/user-management/users/email-registeredi",{email:value})
return true;
}
catch(e){
return false;
}
}
}
}
You don't need to use "new Promise" because vue-resource already do that. Try this:
validations: {
user_form: {
email: {required,email, isUnique(value) {
// standalone validator ideally should not assume a field is required
if (value === '') return true;
// simulate async call, fail for all logins with even length
return this.$http.post("v1/user-management/users/email-registeredi",{email:value}).then((res)=>{
console.log("res is ", res);
return true;
},(err)=>{
return false;
});
}},
role: {required},
password: {required}
}
},

socket.io callback is not recevied in vue.js method?

Using this vue.js method to login users:
loginUser: function () {
socket.emit('loginUser', {
email: this.email ,
password: this.password
}, function() {
console.log('rooms in callback are:', rooms);
});
}
On the server the loginUser event is handled by:
socket.on('loginUser', (newuser,callback)=> {
var body = _.pick(newuser, ['email', 'password']);
console.log('body is:', body);
User.findByCredentials(body.email, body.password).then((user) => {
return user.generateAuthToken().then((token) => {
if (token) {
console.log('token was found');
let rooms = ['Cats', 'Dogs', 'Birds'];
callback(rooms);
} else {
socket.emit('loginFailure', {'msg' : 'Login failure'});
}
}).catch((e) => {
throw e;
});
}).catch((e) => {
socket.emit('loginFailure', {'msg' : 'Login failure'});
throw e;
});
});
I can see 'token was found' printed out in the console but does not recieve the rooms being printed in the browser console. I receive no errors either.
I'm wondering whetehr it is due to how vue.js methods work? And if so, if there is a way around it?
You forgot to specify rooms as argument in the callback
loginUser: function () {
socket.emit('loginUser', {
email: this.email ,
password: this.password
}, function(rooms) { // need to have rooms argument
console.log('rooms in callback are:', rooms);
});
}