In my login page when I enter wrong credentials backend crashes. I don't want my backend to crash. How do I prevent this from happening? I using MongoDb as database along with Nodejs Expressjs for serverside Please can you guys help me identify my mistake and rectify it Thanks a lot!
Login.jsx
import { useState } from "react";
import styled from "styled-components";
import { login } from "../redux/apiCalls";
import { mobile } from "../responsive";
import { useDispatch, useSelector } from "react-redux";
const Container = styled.div`
width: 100vw;
height: 100vh;
background: linear-gradient(
rgba(255, 255, 255, 0.5),
rgba(255, 255, 255, 0.5)
),
url("https://images.unsplash.com/photo-1627281796892-39e266ee50be?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1827&q=80")
center;
background-size: cover;
display: flex;
align-items: center;
justify-content: center;
a {
color: #FFF;
text-decoration: none;
}
`;
const Wrapper = styled.div`
width: 25%;
padding: 20px;
border-radius: 5px;
background-color: black;
`;
const Title = styled.h1`
font-size: 24px;
font-weight: 300;
color: white;
`;
const Form = styled.form`
display: flex;
flex-direction: column;
`;
const Input = styled.input`
flex: 1;
min-width: 40%;
margin: 10px 0;
padding: 10px;
border:none;
border-bottom: 1px solid red;
background-color: black;
color: white;
`;
const Button = styled.button`
width: 40%;
border: none;
padding: 15px 20px;
background-color: red;
color: white;
cursor: pointer;
margin-bottom: 10px;
border-radius: 5px;
&:disabled {
color: green;
cursor: not-allowed;
}
`;
const Link = styled.a`
margin: 5px 0px;
font-size: 12px;
text-decoration: underline;
cursor: pointer;
color: white;
`;
const Error = styled.span`
color: white;
`;
const Login = () => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const dispatch = useDispatch();
const { isFetching, error } = useSelector((state) => state.user);
const handleClick = (e) => {
e.preventDefault();
login(dispatch, { username, password });
};
return (
<Container>
<Wrapper>
<Title>SIGN IN</Title>
<Form>
<Input
placeholder="username"
onChange={(e) => setUsername(e.target.value)}
/>
<Input
placeholder="password"
type="password"
onChange={(e) => setPassword(e.target.value)}
/>
<Button onClick={handleClick} disabled={isFetching}>
LOGIN
</Button>
{/*error && <Error>Something went wrong...</Error>*/}
<Link>DO NOT YOU REMEMBER THE PASSWORD?</Link>
<Link>CREATE A NEW ACCOUNT</Link>
</Form>
</Wrapper>
</Container>
);
};
export default Login;
Server side
auth.js
const router = require("express").Router();
const User = require("../models/User");
const CryptoJS = require("crypto-js");
const jwt = require("jsonwebtoken");
//REGISTER
router.post("/register", async (req, res) => {
const newUser = new User({
username: req.body.username,
email: req.body.email,
password: CryptoJS.AES.encrypt(
req.body.password,
process.env.PASS_SEC
).toString(),
});
try {
const savedUser = await newUser.save();
res.status(201).json(savedUser);
} catch (err) {
res.status(500).json(err);
}
});
//LOGIN
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ username: req.body.username });
!user && res.status(401).json("Wrong credentials!");
const hashedPassword = CryptoJS.AES.decrypt(
user.password,
process.env.PASS_SEC
);
const OriginalPassword = hashedPassword.toString(CryptoJS.enc.Utf8);
OriginalPassword !== req.body.password &&
res.status(401).json("Wrong credentials!");
const accessToken = jwt.sign(
{
id: user._id,
isAdmin: user.isAdmin,
},
process.env.JWT_SEC,
{expiresIn:"3d"}
);
const { password, ...others } = user._doc;
res.status(200).json({...others, accessToken});
} catch (err) {
res.status(500).json(err);
}
});
module.exports = router;
MongoDB database code
User.js
const mongoose = require("mongoose")
const UserSchema = new mongoose.Schema(
{
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
isAdmin: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
module.exports = mongoose.model("User", UserSchema);
CodePudding user response:
const user = await User.findOne({ username: req.body.username });
// sends wrong credentials status here
!user && res.status(401).json("Wrong credentials!");
// but it still proceeds forward
As it proceeds forwards it attempt to send status again even though it already did before. It will crash as it attempts to set headers twice. So, we need to return it anytime it sets headers
if (!user) return res.status(401).json("Wrong credentials!");
Same should be done with this:
OriginalPassword !== req.body.password && res.status(401).json("Wrong credentials!");
Just make sure all your routes only sets headers once. That is, calls res.status().json();
only once.