Search code examples
node.jsreactjsaxioshttp-status-code-401unauthorized

I'm having trouble using axios post in react


When I using axios post error pesistenly comes out. I also installed cors. I have no idea why this happening. Here is my react code.

import React, { useState } from 'react'
import { Link } from 'react-router-dom'

import axios from 'axios'

export default function Login() {

const [Email, SetEmail] = useState('')
const [Password, SetPassword] = useState('')


return (
    <div>

            <h1>Login</h1>
            <input type="text" placeholder="Email" value={Email} onChange={(e) => SetEmail(e.target.value)} />
            <input type="password" placeholder="Password" value={Password} onChange={(e) => SetPassword(e.target.value)} />
            <button type="submit" onClick={(e) => {
                                const config = {
                                    headers: {
                
                                        'Content-Type': 'application/json'
                                    }
                                }
                                const body = JSON.stringify({ Email, Password })
                                axios.post('http://localhost:4000/app/signin', body, config)
                                    .then((response) => console.log(response.data))
            }}>Login</button>
            <div style={{ float: "right", marginTop: "10px" }}>
                <Link to="/signup" style={{ color: "white" }}>
                    SIGN UP
                    </Link>
            </div>

    </div>
)
}

I'm practicing login. I didn't use form tag. Because when I submit data to backend, the console initialized and can't see what's happening. Next is my node.js code.

router.post(
'/signin',
[
    check('email', 'Type proper e-mail').isEmail(),
    check('password', 'Password is required').not().isEmpty()
],
async (request, response) => {
    try{



        const {email, password} = request.body;
        let user = await signUpTemplateCopy.findOne({email});
        const errors = validationResult(request);

        if (!errors.isEmpty()) {
            return response.status(401).json({errors: errors.array()});
        }

        if (!user){
            return response.status(401).json({ msg: "There is no user with this e-mail"});

        }

        let isPasswordMatch = await bcryptjs.compare(password, user.password);

        if (isPasswordMatch) {

        const payload = {
            user: {
                id : user.id
            }
        }
        jwt.sign(
            payload,
            config.get('jwtSecret'),
            (err, token) => {
                if (err) throw err;
                response.json({token});


            }
        )
        
        } else return response.status(401).json({msg: "wrong password"});
        

    } catch (error) {
        console.log(error.msg);
        return response.status(500).json({msg: "Server Error..."});
    }
})

I can't guess even what's the problem is. Please save me from this problem.


Solution

  • For validating email and password I would recommend the express-validator library. You would implement it like so:

    router.post(
      "/signin",
      [
        body("email").isEmail().withMessage("Email must be valid"),
        body("password")
          .trim()
          .notEmpty()
          .withMessage("You must supply a password"),
      ]
    

    You are probably going to need an error handling middleware. The signupTemplateCopy seems like a confusing naming convention to what should be your User model, but you would take that instead and run an if conditional on it like so:

    async (req, res) => {
        const { email, password } = req.body;
    
        const existingUser = await User.findOne({ email });
    
        if (!existingUser) {
          throw new BadRequestError("Invalid Credentials");
        }
    

    I use a little known npm library for that BadRequestError() you see above called @dc_microurb/common@^1.0.7. Also, instead of bcrypt, you may also want to give scrypt a try from the crypto library, but what you have will work.

    I am also not sure about how you are generating a JWT. Let's say you were doing it as I suggest with, const existingUser = await User.findOne({ email }); or in your case, const existingUser = await signUpTemplateCopy.findOne({ email });, then you would take that existingUser or in your case user to generate the JWT like so:

    const userJwt = jwt.sign(
          {
            id: existingUser.id,
            email: existingUser.email,
          },
          process.env.JWT_KEY!
        );
    

    Then you need to store that JWT in a session object which I do not see anywhere in your code, like so:

    req.session = {
          jwt: userJwt,
        };
    

    and then you can finally send back res.status(200).send(user); or in my example, res.status(200).send(existingUser);