Getting 400 Bad Request despite catching the err in angular2+ - node.js

I have designed a login page where login is successful when i put a correct login and password and Login doesn't happen when I put an incorrect username or password which is correct. However, I get this error:
POST http://localhost:3003/login/authenticate 400 (Bad Request)
ERROR HttpErrorResponse {headers: HttpHeaders, status: 400, statusText: "Bad Request", url: "http://localhost:3003/login/authenticate", ok: false, …}
Everything works properly however, I get the error in the console. Like this:
I want the 400 bad request error to not appear in the console. How to do that?
login.component.ts
login(data) {
console.log("Inside Login");
this.authenticateObj = {
username: data.username,
password: data.password
}
this.http.post("http://localhost:3003/login/authenticate",
this.authenticateObj)
.map(Response => Response)
.catch((err) => {
console.log("err =", err)
alert('Login Failed. Username or Password
is incorrect');
return Observable.throw(err);
})
.subscribe((res: Response) => {
console.log("Inside login authenticate subscribe");
this.info = res;
if (this.info.message == 'Login Successful.') {
console.log("test after login = ", this.info);
if (localStorage.getItem('username') &&
localStorage.getItem('token')) {
alert('Login Successful');
this.router.navigate(['/file-upload/wsdl']);
} else {
this.notification.Error('Unauthorized');
}
}
if (this.info.message == 'error') {
alert('Login Failed');
}
else if (this.info.status == 400) {
alert('Login Failed');
}
})
}
login.controller.js
function authenticateUser(req, res, next) {
console.log("Inside authenticateUser = ", req.body)
LoginService.authenticate(req,req.body)
.then(function (token) {
if (token) {
res.setHeader("authorization",token.token);
res.send({
message: 'Login Successful.',
response: token
});
} else if(res.message == 'Username or Password is
incorrect'){
res.status(401).send({
message: 'Unauthorized. '
});
}
else {
console.log("inside controller, else res.status-400");
res.status(400).send({
message: 'Username or password is incorrect'
});
}
})
.catch(function (err) {
console.log("inside controller, catch res.status 400")
// res.status(400).send(err);
res.status(400).send({
message: 'Username or password is incorrect'
});
});
}

In order to handle errors from server properly, you have to catch them in the subcribe() method of the Observable returned by http.post from Rxjs:
this.http.post("http://localhost:3003/login/authenticate", this.authenticateObj)
.subscribe(
(res: Response) => {
// code when no error...
},
err => {
// error handling...
},
() => {
// finally...
}
);

IMO Bad request is an incorrect response by your server for incorrect username/password combination. You can return a "401" or a "200" itself depending on your requirement.
Now if you want the error not to appear in the console then add an error callback in your subscribe().
this.http.post("http://localhost:3003/login/authenticate", this.authenticateObj)
...
// rest of the code
.subscribe((res: Response) => {
// your code
}, (error) => {
// handle the error here, show some alerts, warnings, etc
console.log(error)
})

Related

How to pass the response array from node in the catch block in a fetch promise in React

I am working on a React and Node app and I don't understand how to pass the error given from the back end to the catch block in the fetch in the front end.
The login function uses fetch that throws an error if the server returns a not-ok status. The server also returns an array of errors that I need to display on the front end.
My problem is that when forcing an error and throwing the error to be caught in the catch block of the fetch promise, I cannot feed the catch with the array of errors returned by the back end.
I feed the response to the catch and there when it is logged it says it is an object Response. And it does not have the errors property coming from the back end response.
This is the login function on the front end:
function handleLogin() {
fetch('http://localhost:5000/auth/login', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }),
})
.then((response) => {
if(!response.ok) {
throw Error(response)
}
return response.json()
})
.then((token) => {
localStorage.setItem('token', token);
history.push('/');
window.location.reload();
})
.catch((error) => {
console.log('error: ', error); // error: Error: [object Response]
console.log('error:', error.errors); // undefined
setErrors(error.errors)
})
}
This is the controller of the login in the back end:
exports.login = async (req, res) => {
const { password, username } = req.body;
const hasErrors = validationResult(req);
// VALIDATE INPUTS
if (!hasErrors.isEmpty()) {
console.log('there are errros')
return res.status(401).json({
erros: hasErrors.array(),
});
}
// VALIDATE USER
const user = await User.findOne({ username });
if (!user) {
return res.status(401).send({
erros: [
{
msg: 'Invalid Credentials 1',
},
],
});
}
const isValid = await bcrypt.compare(password, user.password);
if (isValid) {
// SIGN THE JWT
const token = await JWT.sign({ username }, 'mysecret', {
expiresIn: 864_000,
});
return res.json(token);
} else {
return res.status(401).send({
erros: [
{
msg: 'Could not save the user into the db',
},
],
});
}
}

Next.js's API route does not send response

Next.js sends this error when requesting my API route:
API resolved without sending a response for /api/login, this may result in stalled requests.
The content of the API route is, I guess, valid. Most edgecases was solved. I'll also add that the error was occuring when successfully logged.
export default withSession(async (req, res) => {
if (req.method !== "POST") {
return res.status(405).send({ error: "Tylko metoda POST jest dozwolona." });
}
const { username, password } = req.body;
if (!username || !password) {
return res.status(401).send({ error: "Nazwa użytkownika i hasło nie mogą być puste." });
}
try {
const knex = getKnex();
const user = await knex<User>("users").select("*").where("username", username).first();
if (!user) {
return res.status(401).send({ error: "Użytkownik o takiej nazwie nie istnieje." });
}
bcrypt.compare(password, user.password, async function (error) {
if (error) {
return res.status(403).send({ error: "Podane hasło jest nieprawidłowe." });
}
const { password, ...result } = user;
req.session.set("user", result);
await req.session.save();
res.status(200).send({ message: "Zostałeś zalogowany." });
});
} catch (error) {
res.status(error?.status || 500).send({ error: error.message });
console.error(error.stack);
}
});
The withSession function is a utility for handling next-iron-session.
Attempt to add a return before calling the bcrypt and on its final response, such as:
return bcrypt.compare(password, user.password, async function (error) {
if (error) {
return res.status(403).send({ error: "Podane hasło jest nieprawidłowe." });
}
const { password, ...result } = user;
req.session.set("user", result);
await req.session.save();
return res.status(200).send({ message: "Zostałeś zalogowany." });
});
You can delete this warning by exporting a config object to change the default configs.
it tells the server that this route is being handled by an external resolver
export const config = {
api: {
externalResolver: true,
},
}
reference

I am not getting any response when my credentials are wrong in catch while calling login API with axios

I am not getting any response while calling login api from nodejs.
I am handling the catch in frontend as well.
How to get Invalid Credentials message from backend API if credentials doesn't matched.
my Backend login API is -
// api to login user
router.post('/login', function (req, res) {
const valid = validator.isEmail(req.body.email)
if (valid == false) {
var message = { "Success": 0, "Message": "Please enter a valid email." };
res.send(message)
}
userObj.findOne({
email: req.body.email
}).then(user => {
if (!user) {
var message = { "Success": 0, "Message": "User does not exists." };
res.send(message)
} else {
// console.log(bcrypt.compare(req.body.password, user.password))
// var message = { "Success": 1, "User": user };
// res.send(message)
bcrypt.compare(req.body.password, user.password)
.then(isMatch => {
if (isMatch) {
const payload = {
name: user.name,
id: user._id,
email: user.email
}
jwt.sign(payload, 'secret', {
expiresIn: 3600
}, (err, token) => {
if (err) console.error('There is some error in token', err);
else {
res.json({
Success: 1,
token: `${token}`
})
}
})
}
else {
res.json({
Success: 0,
Message: 'Invalid Credentials'
})
}
})
}
})
});
my frontend login action code is -
// Login - get user token
export const loginUser = user => dispatch => {
return axios
.post("http://18.207.190.61:4000/login", {
email: user.email,
password: user.password
})
.then(res => {
// Save to localStorage
// Set token to localStorage
localStorage.setItem("usertoken", res.data.token);
// Set token to Auth header
setAuthToken(res.data.token);
// Decode token to get user data
const decoded = jwt_decode(res.data.token);
// Set current user
localStorage.setItem("username", decoded.name);
dispatch(setCurrentUser(decoded));
return res.data;
})
.catch(err => {
return err;
});
};
finally my login component code is -
this.props.loginUser(user).then((res, err) => {
if (res.Success == "0") {
this.setState({
loading: false,
message: res.Message
});
}
});
How can I get message Message: 'Invalid Credentials' from backend API in front end to print.
Please return response with status codes '200' for success and '401' for invalid credentials and try again. Axios recognises the status codes and tells if there is an error.
if(success)
res.status(200).json({
Success: 1,
token: '${token}'
})
else
res.status(401).json({
Success: 0,
Message: 'Invalid Credentials'
})
Try this once.
1.Remove the catch block in your login action code
2. change your login component code to
this.props.loginUser(user).then((res ) => {
if (res.Success == "0") {
this.setState({
loading: false,
message: res.Message
});
}
});

Post request sends undefined data inn flutter app

I was working on a simple app with login functionality , but im unable to send username and password properly to nodejs server. I have tried encoding it, putting it as Map and FormData, but nothing seems to workout. I console logged the request body and it prints "undefind"
I'm using Dio dart package for making http requests and Redux and redux thunk to dispatch actions .
//Code on My flutter app
ThunkAction<AppState> login(LoginData data) {
return (Store<AppState> store) async {
store.dispatch(IsLoading(true));
try {
Response response = await Dio().post(
"http://10.0.2.2:4000/api/user/login",
data: json.encode({"phone": data.phone, "password": data.password}));
if (response.statusCode == 200) {
print(json.decode(response.data));
store.dispatch(IsLoading(false));
}
} catch (e) {
print("Error :(");
}
};
}
// Code on My nodejs
router.post("/login", (req, res) => {
//this log prints undefined
console.log("Login route: " + req.body.phone);
var cred = {
phone: req.body.phone,
password: req.body.password
};
User.findOne({ phone: cred.phone })
.then(result => {
if (!result) {
res.status(400).json({ msg: "no user" });
} else {
bcrypt.compare(req.body.password, result.password, (err, isMatch) => {
if (isMatch) {
const payload = { id: result._id };
console.log("Logged in :" + payload);
jwt.sign(
payload,
keys.secretOrKey,
{ expiresIn: 7200 },
(err, token) => {
res.status(200).json({
success: true,
token: "Bearer " + token
});
}
);
} else {
res.status(400).json({ msg: err });
}
});
}
})
.catch(err => {
res.status(400).json({ msg: err });
});
});
To access parameter in server side add this header to you request:
HttpHeaders.contentTypeHeader: 'application/x-www-form-urlencoded'

JSON Parse error: Unexpected identifier "Not found"

fetch('http://192.168.120.100:8080/login', {
method: 'POST',
body: JSON.stringify(SignInData),
headers: {
'Content-Type': 'application/json'
}
})
.then((response)=>response.json())
.then((user)=>{
if(user.status=="success"){
alert("success")
console.log("success");
}else{
alert("error")
console.log("fail");
}
})
.catch((error)=>{
console.log("Error, with message::",error)
});
}
and my server code is
router.post('/login', function (req, res) {
User.findOne({ email: req.body.email }).then((user) => {
console.log('testing' + JSON.stringify(user));
if (!user) return res.status(404).send("Not found");
//check password matches
if (user.password == req.body.password) {
user.status = "Success";
res.status(200).send('success');
} else {
res.status(404).send('Invalid Password');
}
})
.catch((err) => {
res.status(500).send(err);
});
});
});
i am working on signin form and my backend is working fine but while running on react native i am getting an error JSON Parse error: Unexpected identifier "Not".is it a json error ?
Looks like the problem is when you are passing the "Not found" in the case user not found , well for that matter even 'success'
On the UI side when you call .then((response)=>response.json()) It tries to change the response to a json format, whereas your API is returning String "Not Found" which does not conform to json structure.
as for solution you can pass JSON in all scenarios, you might need to change your UI accordingly.
router.post('/login', function (req, res) {
User.findOne({ email: req.body.email }).then((user) => {
console.log('testing' + JSON.stringify(user));
var result = {};
if (!user) {
result.message = "Not Found"
return res.status(404).send(result);
}
//check password matches
if (user.password == req.body.password) {
user.status = "Success";
result.message = "Success"
res.status(200).send(user);
} else {
result.message = "Invalid Password";
res.status(404).send(result);
}
})
.catch((err) => {
res.status(500).send(err);
});
});
});

Resources