Optimize verifyKey middleware for hashed API Keys

33 Views Asked by At

I am currently working on a project where I am developing (for now) a read-only API where a user can access information from a DB using generated API keys.

After running some tests using apache bench, it seem like the verifyKey middleware for the API Key authentication is very slow.

Test: 500 getVerse requests with 10 concurrent level.

Results:

WITH verifyKey middleware: 81.737 seconds
WITHOUT verifyKey middleware: 5.158 seconds

I have previously tried hashing the given key in the header of a get request, then querying the database using SQL with the hash, but no matches ever showed up. The problem with that seemed to be that the hashed key was always different to the previously hashed key stored in the database.

So at the moment, the janky solution I came up with was just to get all of the hashed API keys from the database and loop through all of them, using bcrypt.compare to compare each individual hashed key to the hashed key in the header.

Code:

const bcrypt = require("bcrypt");
const cxn = require("../models/db.js");

/** Check whether the API key in the request is in the MySQL key table */
const verifyKey = async (req, res, next) => {
  // Get the API key from the request headers
 //console.log(req.headers)

  const apiKey = req.headers.apikey;

  let query = 
    `SELECT hashed_api_key
      FROM ApiKeys;`;
  cxn.query(query, (err, result) => {
    //console.log(result)
    for (let i = 0;i<result.length;i++){
      bcrypt.compare(apiKey, result[i].hashed_api_key, (e,isMatch)=>{
        try {
          if (isMatch) {
            next();
          } 
        } catch (e){
          res.status(500).json({message: e.message})
        }
      })
    }
  })
};

module.exports = { verifyKey };

Obviously, this doesn't seem very secure and optimal, so what is the correct approach for this problem?

0

There are 0 best solutions below