Error message from server side is not displaying in front end - reactjs

When login gets failed in server side res.status(403).json({ fail: "Login failed" }); message from server side is passing into front end setHelperText(failMessage); How can i get the 'Login Failed' message in front end ?
It is displaying error in chrome console >> Error: Request failed with status code 403
at createError (createError.js:16)
at settle (settle.js:17)
server.js
app.post('/service/login', async (req, res) => {
try {
const userEmail = req.body.email;
const userPassword = req.body.password;
const loginData = await UserModel.findAll({ where: { email: userEmail} });
const password = loginData[0].password;
const email = loginData[0].email;
if(password === userPassword && email === userEmail){
const privilege = loginData[0].privilege;
res.status(200).json({ success: true, privilege, email });
}else{
res.status(403).json({ fail: "Login failed" });
}
} catch (e) {
res.status(500).json({ message: e.message });
}
});
Login.js
const fetchData = async () => {
try {
const res = await axios.post('http://localhost:8000/service/login', { email , password });
console.log("Front End success message:"+res.data.success);
if(res.data.success){
setHelperText("Login successfully");
setValue(res.data.privilege);
setError(true);
}
else{
const failMessage = res.data.fail;
setHelperText(failMessage);
}
} catch (e) {
console.log(e);
}
}

If the response is not success, (403 in your case), catch block will be executed, so move your logic inside the else block to catch block in the Login.js
catch(e) {
const failMessage = e.response.data.fail;
setHelperText(failMessage);
// console.log(e.data.response); -> to print the server response
}

Related

How can I solve: ERR_CONNECTION_REFUSED in React Js for my sign in form

I humbly need your help to resolve the ERR_CONNECTION_REFUSED issue whenever I try to sign in an already signed up user using my chat app that am building in react Js and stream. It will be good if you jus show me what I might have missed by editing my below code. Thank you in advance!
//This is my code//
const { connect } = require('getstream');
const bcrypt = require('bcrypt');
const StreamChat = require('stream-chat').StreamChat;
const crypto = require('crypto');
require('dotenv').config();
const api_key = process.env.STREAM_API_KEY;
const api_secret = process.env.STREAM_API_SECRET;
const app_id = process.env.STREAM_APP_ID;
const signup = async (req, res) => {
try {
const { fullName, username, password, phoneNumber } = req.body;
const userId = crypto.randomBytes(16).toString('hex');
const serverClient = connect(api_key, api_secret, app_id);
const hashedPassword = await bcrypt.hash(password, 10);
const token = serverClient.createUserToken(userId);
res.status(200).json({ token, fullName, username, userId, hashedPassword, phoneNumber });
} catch (error) {
console.log(error);
res.status(500).json({ message: error });
}
};
const login = async (req, res) => {
try {
const { username, password } = req.body;
const serverClient = connect(api_key, api_secret, app_id);
const client = StreamChat.getInstance(api_key, api_secret);
const { users } = await client.queryUsers({ name: username });
if(!users.length) return res.status(400).json({ message: 'User not found' });
const success = await bcrypt.compare(password, users[0].hashedPassword);
const token = serverClient.createUserToken(users[0].id);
if(success) {
res.status(200).json({ token, fullName: users[0].fullName, username, userId: users[0].id});
} else {
res.status(500).json({ message: 'Incorrect password' });
}
} catch (error) {ads
console.log(error);
res.status(500).json({ message: error });
}
};
module.exports = { signup, login }

AXIOS Status 400 Bad Request on React Front End

I am building an authentication component on React.
When the wrong password/username is entered, I am expecting a Status 400 with the message: 'Invalid email or password' on the front end
Instead, I am getting Status 400 with the message: 'Request failed with status code 400'. I used postman to simulate a bad login and I do get the message : 'Invalid email or password'
When I tried a successful login on my frontend, everything works and I get a JWT token.
I also did a console.log on the backend and I can see that the data did reach the backend. The problem seems to be that the error is not handled by the front end properly.
Can someone take a look and let me know what is the problem? thank you.
Backend Post routes
router.post('/signin', async (req, res) => {
console.log(req.body)
let user = await User.findOne({ email: req.body.email })
if (!user) return res.status(400).send('Invalid email or password')
//compare the password with the password in database
const validPassword = await bcrypt.compare(req.body.password, user.password)
if (!validPassword) return res.status(400).send('Invalid email or password')
const token = user.generateAuthToken()
// res.send(token)
res.header('x-auth-token', token).send(_.pick(user, ['_id', 'name)', 'email']))
})
Frontend React
doSubmit = async (e) => {
e.preventDefault()
const { data } = this.state
try {
console.log(data)
await userService.signIn(data)
} catch (ex) {
console.log(ex.message)
if (ex && ex.response.status === 400) {
let errors = { ...this.state.errors }
errors.email = ex.message
this.setState({errors})
}
}
}
userService
import axios from 'axios'
import { SIGN_UP, SIGN_IN } from '../Components/constant/constant';
import { Redirect } from 'react-router-dom';
export default {
register: (user) => {
console.log(user, 'axios')
axios.post(SIGN_UP, {
email: user.email,
password: user.password,
name: user.name
}).then(function (response) {
console.log(response, 'response')
console.log(response)
if (response.status === 200) {
window.location = '/signupsuccessful'
}
})
.catch(function (error) {
console.log(error);
})
},
signIn: async (data) => {
console.log('sign in user service')
await axios.post(SIGN_IN, {
email: data.email,
password: data.password,
})
}
}
I think you just missed the response part of the exception in the doSubmit function of the React code, so you get the exception message and not the response message from the request.
Change
errors.email = ex.message
To
errors.email = ex.response.data
Example
if (ex && ex.response.status === 400) {
let errors = { ...this.state.errors }
errors.email = ex.response.data
this.setState({errors})
}
Nothing is wrong in your code just to get the response from the error case in axios you have to get like so:
...
.catch((error)=>console.log(error.response.data))
EDIT: for more details
So what you have to do in your code is:
Backend
don't send a string i recommend
send a json
res.status(400).send({message:'Invalid email or password'})
FrontEnd
if (ex && ex.response.status === 400) {
let errors = { ...this.state.errors }
errors.email = ex.response.data.message
this.setState({errors})
}

How to request with method get with axios. Send uid, client and token

I'm trying to get data from an API, but it needs me to send -> (client - uid and token information). How do I do this using redux-sagas and axios? BUT it works on the postman.
SAGAS.TS
export function* getListTasks({payload}) {
try {
const resp = yield call(api.get, 'enterprises', {headers: {
client: "nyzcig9rTLqAKeHLmoL4LQ",
'access-token': "Ds23VSssxu2mDafOIHqmcg",
uid: "testeapple#company.com.br"
}});
console.log(payload)
//yield put(setListCompanys(resp.data));
} catch (err) {
Alert.alert(
'ERROR REUQEST',
'ERROR: '+err,
);
}
}
Return Error: [Error: Request failed with status code 401]
I managed to solve my problem, I was making the request wrongly, follow the code: (I hope it helps someone)
export function* signIn({payload}) {
try {
const {email, password} = payload;
const response = yield call(api.post, 'users/auth/sign_in', {
email,
password,
});
const login = {
token: response.headers['access-token'],
uid: response.headers.uid,
client: response.headers.client,
};
if (login) {
api.defaults.headers.Authorization = `Bearer ${login.token}`;
api.defaults.headers['access-token'] = login.token;
api.defaults.headers['uid'] = login.uid;
api.defaults.headers['client'] = login.client;
}
yield put(signInSuccess(login, response.data));
} catch (err) {
Alert.alert(
'Falha na autenticaĆ§Ć£o',
'Houve um erro no login, verifique seus dados: ' + err,
);
yield put(signFailure());
}
}

Why is a user able to login and have a json web token is issued even though user has entered incorrect password?

1.below are the AuthRoutes.js , User.js , RequireAuth.js files with the code.
2.Ive tried changing the email to an invalid un-captured one , and it does report the error "Invalid email or password" which is correct, however when the user enters the incorrect password for that user ,
3. a JSON web token is issued instead of posting the error invalid Email or password as indicated in the code.
const express = require('express');
const mongoose = require('mongoose')
const jwt = require('jsonwebtoken');
const User = mongoose.model('User');
const router = express.Router();
router.post('/signup', async (req,res)=>{
const {name,email,password} = req.body;
try{
const user = new User({name,email,password});
await user.save();
const token = jwt.sign({ userId: user._id},'MY_SECRET_KEY');
res.send({token});
} catch (err) {
return res.status(422).send(err.message);
}
});
router.post('/signin', async (req, res) =>{
const { email, password} = req.body;
if (!email || !password) {
return res.status(422).send({error:'Must provide email and password '})
}
const user = await User.findOne ({ email});
if(!user) {
return res.status(422).send ({error:'Invalid email or password'});
}
try{
await user.comparePassword(password);
const token = jwt.sign ({userId: user._id},'MY_SECRET_KEY');
res.send ({ token });
} catch (err){
return res.status(422).send({error:'Invalid password or email'})
}
});
module.exports = router;
const jwt = require ('jsonwebtoken');
const mongoose = require ('mongoose');
const User = mongoose.model('User');
module.exports = (req,res,next) =>{
const {authorization} = req.headers.body;
//authorization === 'Bearer dfkndlkfgdkgmdlkgmdlkgdkfgmdlfkg(token)'
if (!authorization) {
return res.status (401).send ({error:"You must be logged in"});
}
const token = authorization.replace('Bearer ','');
jwt.verify(token, 'MY_SECRET_KEY', async (err, payload)=>{
if (err){
return res.status(401).send({error:'You must be logged in'});
}
const {userId} = payload;
const user = await User.findById(userId);
req.user = user;
next();
});
};
const mongoose = require('mongoose');
const bcrypt = require ('bcrypt');
const userSchema = new mongoose.Schema({
name:{
type:String,
required: true,
},
email:{
type: String,
unique: true,
required: true,
},
password:{
type:String,
required: true
}
});
userSchema.pre('save', function (next){
const user = this;
if(!user.isModified('password')){
return next();
}
bcrypt.genSalt(10, (err,salt) =>{
if (err){
return next (err);
}
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) {
return next (err);
}
user.password = hash;
next ();
});
});
});
userSchema.methods.comparePassword = function(candidatePassword){
return new Promise ((resolve,reject) => {
bcrypt.compare (candidatePassword, this.password, (err,isMatch) => {
if (err){
return reject (err);
} else {
return resolve(true);
}
});
});
};
mongoose.model('User', userSchema);
Its because your comparePassword is returning a result that isn't checked for / caught.
Change your promise to:
return new Promise ((resolve,reject) => {
bcrypt.compare(candidatePassword, this.password, (err, res) => {
if (err){
reject(err);
} else {
resolve(res);
}
});
});
And then your check to:
const result = await user.comparePassword(password);
if (!result) return res.status(422).send({error:'Incorrect email and/or password'});

JWT gives invalid token

Working locally, my jwt token is invalid but in jwt.io it shows verified signature. Not sure what i am missing. I am having invalid signature whenever i tried to make a call to a api whithin the app.
Link.js
const { Router } = require("express");
const Link = require("../models/Link");
const auth = require("../middleware/auth.middleware");
const router = Router();
router.get("/", auth, async (req, res) => {
try {
const links = await Link.find({ owner: req.user.userId });
res.json(links);
} catch (error) {
res.status(500).json({ message: "Something went wrong, try again" });
}
});
auth.middleware.js
const jwt = require("jsonwebtoken");
const config = require("config");
module.exports = (req, res, next) => {
if (req.method === "OPTIONS") {
return next();
}
try {
const token = req.headers.authorization; // Token
if (!token) {
return res.status(401).json({ message: "No Authorization" });
}
const decoded = jwt.verify(token, config.get("secret"));
req.user = decoded;
next();
} catch (error) {
res.status(401).json({ message: "No Authorization" });
}
};
Links.tsx
const LinksPage: React.FC = () => {
const [links, setLinks] = useState([]);
const fetchLinks = useCallback(async () => {
try {
const fetched = await request("http://localhost:5000/api/link/", "GET", null, {
Authorization: Token,
});
setLinks(fetched);
} catch (error) {
alert(error);
}
}, []);
};
Maybe the "req.headers.authorization" was not what you looking for.
Try to console.log(req.headers.authorization) F12 in chrome, firefox.
I suggest you also POSTMAN (free software). It help me a lot for debugging the back end (server side).
I solved the problem. I had to json.parse(token) which stored in the client in order to jwt.verify(token, secret), but instead i was verifying string that contains object of token and userId.

Resources