or: Cannot read properties of undefined (reading 'email') - node.js

I am sending an auth request from chrome to my backend, there is payload chrome developer tool, it seems to have received the object, but I am backend
or: Cannot read properties of undefined (reading 'email')
It gives an error, I printed req.body from the console, it is empty object, what can I do?
backend
postmande works fine and logs in successfully
const { body: { user } } = req
console.log(req.body)
const userLogin = new User();
if (!user.email && !user.password) {
return res.status(402).json({
errors: "Eposta veya şifre zorunlu 😊 ! ",
});
}
return passport.authenticate('local', {
session: false,
successRedirect: '/home',
failureRedirect: '/login'
}, (err, passportUser, info) => {
if (err) {
return next(err)
}
if (passportUser) {
console.log(passportUser)
const user = passportUser
user.token = userLogin.generateJWT(user.email, user.id);
return res.json({ user: passportUser })
}
return res.status(400).json({ message: info });
})(req, res, next)
react fetch (client)
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
// const token = localStorage.getItem("X-CSRF-TOKEN");
const loginProccsess = async (e) => {
e.preventDefault()
const data = {
"user": {
email,
password
}
}
fetch("/api/auth/login", {
method: "POST",
mode: "cors",
// credentials: "some-origin",
header: {
"Content-type ": "application/json"
},
redirect: "follow",
body: JSON.stringify(data)
}).then((res) => {
console.log(res)
})
.catch(err => console.log(err))
}

Related

Why is req.body empty {} (GET REQUEST)

This is my Frontend code
const fetchData = () => {
const options = {
method: 'GET',
url: 'http://localhost:1337/user/chart',
headers: {'x-access-token': sessionStorage.getItem('token')},
body: [chartData.datasets]
}
axios.request(options).then((response) => {
console.log(response)
}).catch((error) => {
console.error(error)})
}
This is backend
app.get('/user/chart', async (req, res) => {
const token = req.headers['x-access-token']
if (!token){
return res.status(404).json({ success: false, msg: "Token not found" });
}
try {
const decoded = jwt.verify(token, process.env.access_secret)
const email = decoded.email
await User.updateOne(
{ email: email },
{ $set: {} },
)
console.log(req.body)
return res.status(200).json({message: 'ok', label:[]})
} catch (error) {
console.log(error)
res.json({ status: 'error', error: 'invalid token' })
}
})
When I console.log(req.body) it is an empty {}.
Why is it empty?
I am using a GET request to retrieve the chart data
Axios API does not accept body on get get request you can send parameters with params example
const url = '/user/chart';
const config = {
headers: {'x-access-token': sessionStorage.getItem('token')},
params:{someKey:chartData.datasets}
};
axios.get(url, config)
Axios doesn't support setting a body for a get request, see the docs or this related question.
Though, I'd also recommend to reconsider your design. Typically the body isn't used in a GET request. If you're sending data to the server, you likely want to use POST or PUT instead. If you just want to pass a parameter, then you likely want to use request parameters.
If you absolutely need to send a body in your GET request, then you'll need to use a different tool.
frondend //
const fetchData = () => {
const options = {
method: 'POST',
url: 'http://localhost:1337/user/chart',
headers: {'x-access-token': sessionStorage.getItem('token')},
body: {name : "xx",mail:"xx#"}
}
axios.request(options).then((response) => {
console.log(response)
}).catch((error) => {
console.error(error)})
}
backend //
app.post('/user/chart', async (req, res) => {
const {name , mail} = req.body
const token = req.headers['x-access-token']
if (!token){
return res.status(404).json({ success: false, msg: "Token not found" });
}
try {
const decoded = jwt.verify(token, process.env.access_secret)
const email = decoded.email
await User.updateOne(
{ email: email },
{ $set: {} },
)
console.log(req.body)
return res.status(200).json({message: 'ok', label:[]})
} catch (error) {
console.log(error)
res.json({ status: 'error', error: 'invalid token' })
}
})Ï

Post request from client gives undefined (nodejs)

I'm doing clienten post operation on my node js server, it works fine from postman, but clienten undefend returns
as i said from postman
{ "user": {
"email": "levlaaaaa#levla.com",
"password": "123" } }
When I throw the object, it works fine, but it returns undefined on the cilient side.
client request file (react)
const loginProccsess = async (e) => {
e.preventDefault()
const data = {
"user": {
"email":email,
"password": password
}
}
// return console.log(JSON.stringify(data))
await fetch("/api/auth/login", {
method: "POST",
mode: "cors",
// credentials: "some-origin",
header: {
"Content-type ": "application/json"
},
redirect: "follow",
body: JSON.stringify(data)
}).then((res) => {
console.log(res)
})
backend login.js (login router request)
router.post("/login", authOP, (req, res, next) => {
const { body: { user } } = req
const userLogin = new User();
console.log(user)
if (!user.email && !user.password) {
return res.status(402).json({
errors: "Eposta veya şifre zorunlu 😊 ! ",
});
}
return passport.authenticate('local', {
session: false,
successRedirect: '/home',
failureRedirect: '/login'
}, (err, passportUser, info) => {
if (err) {
return next(err)
}
if (passportUser) {
console.log(passportUser)
const user = passportUser
user.token = userLogin.generateJWT(user.email, user.id);
return res.json({ user: passportUser })
}
return res.status(400).json({ message: info });
})(req, res, next)
})
// app.js(server) (main file)
app.use(Sentry.Handlers.requestHandler());
app.use(cookieParser());
app.use(express.json())
app.use(cors());
app.use(session({
resave: false,
saveUninitialized: true,
secret: 'secret'
}))
app.use(passport.initialize())
app.use(passport.session())

Set-Cookie not sended on HTTP response header

i´m creating a Authentication page with React and Express. I'm using JWT too.
I´ve made this route in the back:
server.js
...
app.use(
cookieSession({
name: "prode_session",
secret: "MIOURI_PRODE_SECRET", //add to .env variable
httpOnly: false,
})
);
app.use(cors());
...
auth.routes.js
app.post("/signin", controller.signin);
user.routes.js
app.get(
"/user",
[authJwt.verifyToken],
(req, res) => res.send(true)
)
auth.controller.js
exports.signin = async (req, res) => {
const user = await Users.findOne({
where: { email: req.body.email },
});
try {
if (!user) {
return res.status(404).send({ message: "User Not found." });
}
const passwordIsValid = bcrypt.compareSync(
req.body.password,
user.password
);
if (!passwordIsValid) {
return res.status(401).send({
message: "Invalid Password!",
});
}
const token = jwt.sign({ id: user.id }, config.secret, {
expiresIn: 84000, //24hours
});
req.session.token = token;
console.log(req.session);
return res.status(200).send({
isLogged: true,
id: user.id,
email: user.email,
suscripcion: user.suscripcion,
preference_id: user.preference_id,
token,
});
} catch (error) {
console.log(error);
}
};
authJWT.js
verifyToken = async (req, res, next) => {
let token = req.session.token;
console.log(`THIS IS THE TOKEN: ${token}`);
if (!token) {
return res.status(403).send({
message: "No token provided",
});
}
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
console.log(err);
return res.status(401).send({
message: "Unauthorized!",
});
}
req.id = decoded.id;
next();
});
};
const authJwt = { verifyToken };
module.exports = authJwt;
When I test this with POSTMAN, it works Ok, I mean, if first I try to make the GET request, the response is "No token provided", but if I signin first, generate the token and then make the GET request, I get true.
The problem is when I try to implement this in the front.
I have this Login component in React in which I make a POST request with the credentials:
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch("http://localhost:3000/signin", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
body: JSON.stringify({
email,
password,
}),
});
const data = await response.json();
console.log(data);
if (data.isLogged && data.suscripcion === true && data.token) {
await tokenAvailable()
//navigate(`/masthead/${email}&${data.isLogged}&${data.id}`);
} else if (data.isLogged && data.suscripcion === false) {
navigate("/suscripcion", {
state: { preference_id: data.preference_id },
});
} else {
window.alert("Invalid Login");
}
} catch (error) {
console.log(error);
}
};
async function tokenAvailable() {
const user = await fetch("http://localhost:3000/user", {
method: "GET",
mode: "cors",
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
});
const response = await user.json();
setUser(await response);
console.log(await response);
return response;
}
When I make the POST, the GET request is executed (tokenAvailable function) after receiving the response, but I receive "No token Provided" while I expect to receive "true" as in Postman.
From what I debug, the authJWT.js file, is not receiving nothing from the req.session.token.
When I compare the headers from postman and the browser, in postan the SET-cookie key appears, but in the browser not.
postman:
browser:
I need some help here. I´ve been strugling with this for almost 3 days.
I found a solution for this. Apparently, the HttpOnly Cookie approach works if the React app and the back-end server hosted in same domain. So we need to use http-proxy-middleware for local development.
I´ve tried to install the http-proxy-middleware but a lot of errors came, so I decided to store de JWT in the localstorage.

CORS express js dont save a cookie

I read a lot of questions like this but no one is usefull for me.
I have a MERN app. I use Heroku to deploy. In my local environent everithing works but in heroku the login crash. I use Cookies. and try every posible configuration.
Please help.
This is my login server:
login: async (req, res) => {
try {
const { email, password } = req.body;
const user = await Users.findOne({ email })
//console.log(user)
if (!user) return res.status(400).json({ msg: "Usuario inexistente" })
const isMatch = await bcrypt.compare(password, user.password)
if (!isMatch) return res.status(400).json({ msg: "Clave erronea" })
//If login success, craete access Token and refresh
const accesstoken = createAccessToken({ id: user._id })
const refreshtoken = createRefreshToken({ id: user._id })
//console.log(refreshtoken)
res.cookie('refreshtoken', refreshtoken, {
sameSite: 'strict',
httpOnly: true,
path: '/user/refresh_token',
maxAge: 7 * 24 * 60 * 60 * 1000 //7days
})
res.json({ accesstoken })
} catch (err) {
return res.status(500).json({ msg: err.message })
}
},
Here server conf.
//MIDDELEWARES
app.use(express.json())
app.use(cookieParser())
//app.use(cors())
/*app.use(cors({
credentials: true,
origin: 'https://gabymanualidades.herokuapp.com/'
}))*/
app.use(cors({origin: 'https://*****.herokuapp.com', methods: ['POST', 'PUT', 'GET', 'OPTIONS', 'HEAD'], credentials: true, headers: 'Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Request-Method' }))
app.use(fileUpload({
useTempFiles: true
}))
And client:
const loginSubmit = async e => {
e.preventDefault()
try {
//await axios.post('/user/login', { ...user })
const res=await axios.post('/user/login', { ...user }, {
headers: {
'Content-Type': 'application/json'
},
withCredentials: true,
baseURL: "*****.herokuapp.com"
})
console.log(res)
localStorage.setItem('firstLogin', true)
//window.location.href = "/products";
} catch (err) {
alert(err.response.data.msg)
}
}
Thak you very much!
Screenshot:
It is as if I logged in without saving the cookie since then I can't get it again here:
useEffect(() => {
const firstLogin = localStorage.getItem('firstLogin')
if (firstLogin) refreshToken()
}, [])
const refreshToken = async () => {
try {
console.log("aca problema")
const res = await axios.get('/user/refresh_token', {
headers: {
'Content-Type': 'application/json'
},
withCredentials: true,
baseURL: "https://young-wildwood-03509.herokuapp.com/"
})
setToken(res.data.accesstoken)
setTimeout(() => {
refreshToken()
}, 10 * 60 * 1000)
} catch (err) {
alert(err.response.data.msg)
}
}
Server:
refreshToken: (req, res) => {
try {
//console.log(req.cookies)
const rf_token = req.cookies.refreshtoken;
if (!rf_token) return res.status(401).json({ msg: "Plase Login or registeer" })
jwt.verify(rf_token, process.env.REFRESH_TOKEN_SECRET, (err, user) => {
if (err) return res.status(400).json({ msg: "Plase Login or registerr" })
const accesstoken = createAccessToken({ id: user.id })
//res.json({user, accesstoken})
console.log({ accesstoken })
res.json({ accesstoken })
})
//res.json({ rf_token })
} catch (err) {
return res.status(500).json({ msg: err.message })
}
},

How do i redirect in node.js

I would like to be able to redirect from registration-page to login-page on successfull registration and again from login-page to home-page afteer successfull login.
I dont know what methods to use or where to call them.
This is the register call.
app.post("/api/register", async (req, res) => {
const { username, password: plainTextPassword } = req.body;
const password = await bcrypt.hash(plainTextPassword, 10);
try {
const response = await User.create({
username,
password
})
console.log("User created", response)
} catch (error) {
if (error.code === 11000) {
return res.json({ status: "error", error: "Username already in use" })
}
throw error
}
res.json({ status: "ok" });
});
This is the script
<script>
const form = document.getElementById("reg-form");
form.addEventListener("submit", registerUser);
async function registerUser(event) {
event.preventDefault();
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const result = await fetch("/api/register", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
username,
password
})
}).then((res) => res.json())
if (result.status === "ok") {
alert("Success");
} else {
alert(result.error)
}
}
</script>
</body>
</html>
You should return the line that redirects
return res.redirect('/UserHomePage');

Resources