Emilis
Emilis

Reputation: 162

How to make auth with react and node.js express

I made nice login form using react, now I want to set it up with my back-end and I tried to write some api to authenticate users login. I know that this is wrong way. Could someone correct my Node.js side how should I make it to work? React login:

 function postLogin() {
axios
  .get(prefix + '/api/login/', {
    params: { username: userName, password: password },
  })
  .then((result) => {
    if (result.status === 200) {
      setAuthTokens(result.data);
      setLoggedIn(true);
    } else {
      setIsError(true);
    }
  })
  .catch((e) => {
    setIsError(true);
  });

}

Node.js router:

router.get('/api/login/', async function (req, res, next) {
  console.log(req.query.username);
  console.log(req.query.password);
  // res.sendStatus(200);
  db.checkAuth(req.query.username, req.query.password)
      .then((result) => res.sendStatus(200))
      .catch((error) => res.sendStatus(403)); // Corrected line
});

Node.js DB function:

 exports.checkAuth = (username, password) => {
  return new Promise((resolve, reject) => {
    con.query(
      "SELECT * FROM users WHERE username= $1 AND password = $2",
      [username, password],
      (err, result, fields) => {
        if (err) reject(err);
        if(bcrypt.compareSync(password, result.password)){
          console.log("password matched");
          resolve(result);
        }
      }
    );
  });
};

DB:

enter image description here

And When i write down my login info and try to log in in my pm2 monit enter image description here

Upvotes: 0

Views: 122

Answers (3)

Emilis
Emilis

Reputation: 162

Edited db query function like this, and it solved the problem.

exports.checkAuth = (username, password) => {
  console.log('username: ' + username + ' and password: ' + password);
  return new Promise((resolve, reject) => {
    con.query(
      "SELECT password FROM users WHERE username= ?",
      [username],
      (err, result, fields) => {
        if (err) reject(err);
        if (bcrypt.compareSync(password, result[0]['password'])) {
          console.log('password matched');
          resolve(result);
        }
      }
    );
  });
};

Upvotes: 0

Oliver B.
Oliver B.

Reputation: 48

One thing you should definitely do it not hash your password in the frontend but rather in the backend. This way, you are not vulnerable to a pass-the-hash attack.

Also, set up HTTPS and send your username and password in the HTTP body (Not as a URL parameter). In the backend, you can just query for the hashed password of the given username and compare it with the password sent from Frontend. If you are using bcrypt (based on your provided screenshot), this could look something like:

con.query(`SELECT password FROM users WHERE username='${username}'`, (result) => {
    if(bcrypt.compareSync(password, result.data[0]["password"])){
        // Password correct, return sessionId as response to frontend
    }
})

You could then create a sessionId that you return when he successfully logged in. (There are many ways how you can do authentication. This is just a simple base solution)

This sessionId is stored in the cookies and sent to the backend (in the HTTP headers) with every backend-request.

Hope this could help!

Upvotes: 1

landyrev
landyrev

Reputation: 163

You should properly catch checkAuth method error and send corresponding response

router.get('/api/login/:username/:password', async function (req, res, next) {
    db.checkAuth(req.params.username, req.params.password)
        .then((result) => res.sendStatus(200))
        .catch((error) => res.sendStatus(403)); // Corrected line
});

UPD

Also the way you compose your query is vulnerable to SQL Injections. Use parameterized query to avoid it.

exports.checkAuth = (username, password) => {
  return new Promise((resolve, reject) => {
    con.query(
      "SELECT * FROM users WHERE username = $1 AND password = $2",
      [username, password],
      (err, result, fields) => {
        if (err) reject(err);
        resolve(result);
      }
    );
  });
};

Upvotes: 1

Related Questions