Displaying error messages from Node API on FrontEnd console (React App) - javascript

I'm building Node & React application and I'm working on authentication now. For example when someone will type e-mail that already exist in database, I would like to send a response with error with proper status and message that email already exist.
I'm already done with sending errors when it's needed. Problem is that even if I pass error message within, I can not display it on frontend.
back-end (Node):
User.find({ email: email })
.then(user => {
if (user.length >= 1) {
return res.status(409).json({
message: 'Mail exists' // <-- I want to pass message here
})
}
front-end (React):
axios.post('http://localhost:3000/user/signup', newUser)
.then(response=> {
dispatch({
type: actionTypes.SIGNUP_SUCCESS
})
localStorage.setItem('JWT_TOKEN', response.data.token)
axios.defaults.headers.common['Authorization'] = response.data.token
})
.catch((err)=> {
console.log(err.message) // <-- I want to display message here
})
My actual result is that i see Request failed with status code 409 in my console.
Therefore I would like to see Mail exists.
Thank You for help :)
Best regards.

// you can try below code in your catch block
.catch((err)=> {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
if (err.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
}
})

I agree with Mohammed, you can find error message under data property.
console.log(error.response.data.message);

Related

node js backend security header

im trying to make a login endpoint/api, and i am sending the user login data through the authentication headers, is that okay for the security?
the authorization headers is actually contains an object, it is encoded to a Base64, it contains user data like hashed password (not hashed yet in this code), username, and some sort of a serverkey (to authorize if it is the right client that sending an api request), just wanna make sure if it is secure or not..
const aFunction = (req, res) => {
require('crypto').randomBytes(48, function(err, buffer) {
const token = buffer.toString('hex');
const auth = JSON.parse(Buffer.from(req.headers.authorization, 'base64').toString('ascii'))
if(auth.serverkey == version["serverkey"]){
loginUser(auth.username,token).then(data =>{
if (data.rows.length < 1 || data.rows[0].password != auth.password) {
res.send({
status: "failed",
message: "Username/Password is wrong",
status_code: 400
})
}else{
res.send({
status: "success",
message: "successfully logged in",
status_code: 200, token: token
})
}
})
}else{
res.send({
status: "failed",
message: "Unauthorized Client",
status_code: 401
})
}
});
}
I would add a check for if (req.secure) to your code, and reject any non-https request coming your way. (Don't do this if your nodejs program is behind a reverse proxy.)
Users with browsers can see everything you send back and forth to your server, whether via https or http. (devtools) So, if by reading your headers they can figure out how to send you malicious headers, then somebody will. And base64 encoding has exactly the same security as no encoding at all. So salt and hash your passwords. Use the bcrypt package or jwts.
I would handle errors this way, by calling next() with an error parameter rather than by using .send() to deliver a failure message. Use this sort of code.
const createError = require('http-errors')
...
const myfunction (req, res, next) {
...
if (!req.secure) return next(createError(403, 'https required'))
...
});

Promise Resolved Not Exiting

I'm not sure why my function is not exiting after running. The code does not exit execution after resolving a promise.
I am using Firebase Admin SDK to send a message with the following:
var message = {
data: {
score: '850',
time: '2:45'
},
topic: topic
};
admin.messaging().sendAll([message])
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
after printing to the console 'Successfully sent message:' the code console is still running and not return. What am I doing wrong?
For reference here is the signature of the firebase message send:
send(message: admin.messaging.Message, dryRun?: boolean): Promise<string>;
There might be something in the Firebase Admin SDK that is keeping the process from exiting. You can force the process to exit when you're done by simply adding process.exit(0) to the end of the then callback, if that's when you want it to terminate.
If you think this behavior is a bug, you can file it on the Firebase Admin SDK GitHub.

React/Redux - Handling errors and error codes

I am wondering what is the best way for me to be handling errors, and when I should be using error codes in response from my API in conjunction with an errors object.
I have just started building a multi-part form in react, every time a user moves onto the next step in the form I am sending a request to the API to validate the data before moving onto the next step, and sending back a response of true/false with an errors object if they exist.
My question is, when I am returning generic errors, e.g:
if( hasErr == true ) {
res.status(200).json({
success: false,
errors: errorsObject
});
}
Should I be sending a status of 200 back, or should I be sending back a response with an error code somewhere in the 400 range?
Currently on the client side when I am recieving a response, my basic redux action looks like this:
this.props.createlistingAction(this.state).then(
(res) => {
if( res.payload.success == true ) {
console.log('Success!');
} else {
console.log('We have errors!');
this.setState({ errors: res.payload.errors });
}
console.log(res);
//this.props.history.push('/'),
},
(err) => { // error
console.log(err.response);
this.setState({errors: err.response.data.errors, isLoading: false});
}
);
Is it ok to be handling errors like this? Or if you do suggest I send back a 400 error response, how should I be getting these errors when the payload only contains a generic error "Error: Request failed with status code 400 at createError"?
Thanks
You can also return a content with a status code different by 200.
So you should easily return the HTTP Status Code related to the error and the error details in the body of your response.

Not able to respond to custom error message sent from express

This problem annoys me, because I know it has something to do with me not understanding the issue properly - which makes it really hard to track down answers for, despite spending hours reading and trying different things.
My question/problem is this, I am saving a user to a mongodb database when they signup, my schema doesn't allow for duplicate emails, and sends me back an error. I am able to console log the error in the terminal, but I am having problems sending it back to the client. Or I'm having a problem doing something with it, if it comes back, I'm not too sure where in those two steps I am losing access to the error message.
Here is my POST route for saving the user:
router.post('/users', (req, res) => {
let body = _.pick(req.body, ['email', 'password']);
let user = new User(body);
user.save().then(() => { // this all works and will save the user, if there are no errors
return user.generateAuthToken();
}).then((token) => {
res.header('Authorization', `Bearer ${token}`).send(user);
}).catch((err) => { // This is where my problem is
console.log(err); // This will log the mongodb error here, about duplicate emails
res.status(500).send(err); // I'm trying to send the mongodb error message back to the client to display it on the screen (I will handle making the message friendly to read, once I can get this to work)
});
});
So my catch is getting the mongo error, and then I try to respond with it, by sending it to the client.
Here is my client side code:
axios({
method: 'post',
url: '/auth/users',
headers: {
'Content-Type': 'application/json'
},
data: {
email,
password
}
}).then((res) => {
console.log('this is the response', res);
if (res.status === 200) {
var authToken = res.headers.authorization.split(' ')[1];
authenticateUser(authToken);
this.props.history.replace('/dashboard');
} // This all works fine for a signup with no errors
}).catch((err) => {
console.log('Signup error:', err);
// I am expecting the above line of code to log the long Mongodb
// error message that I am sending back in my res.status(500).send(err)
// catch call from the server, but instead all I am getting is
// "Signup error: Error: Request failed with status code 500"
});
Either I'm not sending the error correctly, or I'm not handling it correctly when it comes back, but I have no idea which it is or why.
I can't even send back res.status(500).send('some string here') and access that string.
Thanks
Update
So I just checked in postman, by sending a POST that could cause the error, and I am getting the correct response sent through.
My server catch actually looks like this:
.catch((err) => {
res.status(500).send({message: err.message});
});
And the postman response body looks like this:
{
"message": "E11000 duplicate key error collection: authBoilerplate.users index: email_1 dup key: { : \"email#example.com\" }"
}
So I'm just not handling it correctly in my client side code, still at a loss though.
Thanks everyone, I was able to find the answer to my question, so I'm posting it here in the hope that it might help someone else.
I was definitely sending my custom error message back, I just wasn't handling it properly on the client side.
When I was using a catch call on the client and logging the error, I was expecting to see everything included in the error. It turns out that the error comes back with a response property error.response, and that is where all the messaging is.
So changing my catch call to this:
axios(//... send post in here)
.then(// ... same as in my question)
.catch((err) => {
console.log('error', err);
console.log('error response', err.response); // this is where the actual error response message is error.response.message
});
resulted in logging the stack trace and the error response:
error Error: Request failed with status code 500
at createError (eval at <anonymous> (bundle.js:541), <anonymous>:16:15)
at settle (eval at <anonymous> (bundle.js:847), <anonymous>:18:12)
at XMLHttpRequest.handleLoad (eval at <anonymous> (bundle.js:520), <anonymous>:77:7)
error response Object {data: Object, status: 500, statusText: "Internal Server Error", headers: Object, config: Object…}
I was still expecting to be able to see that I had access to that 'response' property by logging just the error, so if anyone has any insight into that, it would be great to include in the comments.
Another way of solving this is by converting the error to string.
.catch((err) => {
res.status(500).send(err.toString());
});

How to catch the server response, even if 400 bad request error occured?

Consider following code. It's just a simple http post request with axios library.
axios.post('http://localhost/users', this.state)
.then(function(response) {
if (response.status == 201) {
browserHistory.push('/features');
}
})
.catch(function(error) {
console.log(error);
})
If user enters a wrong data to an input, the response from server holds info, e.g.
password has to be longer then...
mail missing the # sign
etc...
but unfortunately, I don't know how to get into that response if there's a 400 bad request status. It just shows the error, but I'm unable to get the response.
If the response status is 201, it properly shows the response. But in case of 400, even if I change the condition and add else if (response.status == 400) { console.log(response) } it doesn't show up the response.
Any help highly appreciated.
Just looking at the axios documentation, it looks like the response should be exposed in the error object (i.e. console.log(error.response)).
More information about different info provided when the response code falls out of 2xx here: https://github.com/mzabriskie/axios#handling-errors
you need to log the data of the response:
axios.post('http://localhost/users', this.state)
.then(function(response) {
browserHistory.push('/features');
})
.catch(function(error) {
console.log(error.response.data); // this is the part you need that catches 400 request
});

Categories