0

I'm developing a JavaScript/MySQL RESTful API for a business manager system using Express, Body-parser and MySQL. Currently, I am working on access tokens. Before any API call, the body must include an API key that is being verified by the API. In every API call function, I first check if the access token exists and if so, the API executes MySQL commands and sends back results. The important thing is that I want to create a function that checks whether the access token exists and returns true or false. However, I can't figure out how to return this boolean value from the conn.query() method. Any help will be very much appreciated, I am desperate. Here is my code:

function checkApiKey(apiKey) {
  let sql = "SELECT * FROM apikeys WHERE apikey = '" + apiKey + "'";
  conn.query(sql, (err, results) => {
    if (err) throw err;

    if (results.length > 0) return true;

    return false;
  });
}

app.get("/api/users",(req, res) => {
  if (checkApiKey(req.body.apiKey)) {
    let sql = "SELECT * FROM users";
    let query = conn.query(sql, (err, results) => {
      if (err) throw err;
      res.send(results);
    });
  }
});

However, the checkApiKey() method returns undefined...

tomasxboda
  • 539
  • 3
  • 15
  • your current code suffer from SQL injection. – apple apple Sep 26 '20 at 12:53
  • Seealso [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – apple apple Sep 26 '20 at 12:56
  • @appleapple yeah I know, I am surely going to take care of it after everything works as expected. Thank you for your answer! – tomasxboda Sep 26 '20 at 13:29

1 Answers1

1

Your checkApiKey function returns undefined, because your logic returns true or false within sql's callback function.

I'd recommend another approach, using checkApiKey as middleware function:

const checkApiKey = (req, res, next) => {
  conn.query("SELECT * FROM apikeys WHERE apikey = ?", [req.body.apiKey], (err, result) => {
    if (err) throw err
    if (results)
      next() // continue to next router function
    else
      res.status(403).end('Unauthorized') // resolve with 403
  })
}

app.get("/api/users",
        checkApiKey, // middleware auth function
        (req, res) => {
  conn.query("SELECT * FROM users", (err, results) => {
    if (err) throw err;
    res.send(results)
  })
})

ΔO 'delta zero'
  • 3,506
  • 1
  • 19
  • 31
  • This is exactly what I was looking for, works like a charm, thanks! One more question regarding your answer, what is the difference between implementing the ```req.body.apiKey``` into the sql query string and your approach with the question mark and the value as a second argument? – tomasxboda Sep 26 '20 at 13:32
  • Glad to be of help :) Passing values to queries thru `?`s helps mainly with escaping the values to prevent SQL injection attacks. Also I find the query a bit cleaner :-) See https://www.npmjs.com/package/mysql#escaping-query-values – ΔO 'delta zero' Sep 26 '20 at 14:09