diff --git a/.changeset/swift-pumpkins-knock.md b/.changeset/swift-pumpkins-knock.md
new file mode 100644
index 000000000..eca1d97df
--- /dev/null
+++ b/.changeset/swift-pumpkins-knock.md
@@ -0,0 +1,6 @@
+---
+'@verdaccio/auth': patch
+'verdaccio-htpasswd': patch
+---
+
+Refactor htpasswd plugin to use the bcryptjs 'compare' api call instead of 'comparSync'. Add a new configuration value named 'slow_verify_ms' to the htpasswd plugin that when exceeded during password verification will log a warning message.
diff --git a/packages/auth/src/auth.ts b/packages/auth/src/auth.ts
index 9fb136c5c..2ee660a71 100644
--- a/packages/auth/src/auth.ts
+++ b/packages/auth/src/auth.ts
@@ -111,7 +111,7 @@ class Auth implements IAuth {
     };
     let authPlugin;
     try {
-      authPlugin = new HTPasswd(plugingConf, pluginOptions);
+      authPlugin = new HTPasswd(plugingConf, pluginOptions as any as PluginOptions<HTPasswdConfig>);
     } catch (error: any) {
       debug('error on loading auth htpasswd plugin stack: %o', error);
       return [];
diff --git a/packages/plugins/htpasswd/README.md b/packages/plugins/htpasswd/README.md
index 7caff08f4..c512b162c 100644
--- a/packages/plugins/htpasswd/README.md
+++ b/packages/plugins/htpasswd/README.md
@@ -30,7 +30,26 @@ As simple as running:
             # Hash algorithm, possible options are: "bcrypt", "md5", "sha1", "crypt".
             #algorithm: bcrypt
             # Rounds number for "bcrypt", will be ignored for other algorithms.
+            # Setting this value higher will result in password verification taking longer.
             #rounds: 10
+            # Log a warning if the password takes more then this duration in milliseconds to verify.
+            #slow_verify_ms: 200
+
+### Bcrypt rounds
+
+It is important to note that when using the default `bcrypt` algorithm and setting
+the `rounds` configuration value to a higher number then the default of `10`, that
+verification of a user password can cause significantly increased CPU usage and
+additional latency in processing requests.
+
+If your Verdaccio instance handles a large number of authenticated requests using
+username and password for authentication, the `rounds` configuration value may need
+to be decreased to prevent excessive CPU usage and request latency.
+
+Also note that setting the `rounds` configuration value to a value that is too small
+increases the risk of successful brute force attack. Auth0 has a
+[blog article](https://auth0.com/blog/hashing-in-action-understanding-bcrypt)
+that provides an overview of how `bcrypt` hashing works and some best practices.
 
 ## Logging In
 
diff --git a/packages/plugins/htpasswd/src/htpasswd.ts b/packages/plugins/htpasswd/src/htpasswd.ts
index ee7469453..6e7f6829d 100644
--- a/packages/plugins/htpasswd/src/htpasswd.ts
+++ b/packages/plugins/htpasswd/src/htpasswd.ts
@@ -19,9 +19,12 @@ export type HTPasswdConfig = {
   file: string;
   algorithm?: HtpasswdHashAlgorithm;
   rounds?: number;
+  max_users?: number;
+  slow_verify_ms?: number;
 } & Config;
 
 export const DEFAULT_BCRYPT_ROUNDS = 10;
+export const DEFAULT_SLOW_VERIFY_MS = 200;
 
 /**
  * HTPasswd - Verdaccio auth class
@@ -30,30 +33,21 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
   /**
    *
    * @param {*} config htpasswd file
-   * @param {object} stuff config.yaml in object from
+   * @param {object} options config.yaml in object from
    */
   private users: {};
-  private stuff: {};
-  private config: {};
-  private verdaccioConfig: Config;
   private maxUsers: number;
   private hashConfig: HtpasswdHashConfig;
   private path: string;
+  private slowVerifyMs: number;
   private logger: Logger;
   private lastTime: any;
   // constructor
-  public constructor(config: HTPasswdConfig, stuff: PluginOptions<{}>) {
+  public constructor(config: HTPasswdConfig, options: PluginOptions<HTPasswdConfig>) {
     this.users = {};
 
-    // config for this module
-    this.config = config;
-    this.stuff = stuff;
-
     // verdaccio logger
-    this.logger = stuff.logger;
-
-    // verdaccio main config object
-    this.verdaccioConfig = stuff.config;
+    this.logger = options.logger;
 
     // all this "verdaccio_config" stuff is for b/w compatibility only
     this.maxUsers = config.max_users ? config.max_users : Infinity;
@@ -88,25 +82,41 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
       throw new Error('should specify "file" in config');
     }
 
-    this.path = Path.resolve(Path.dirname(this.verdaccioConfig.config_path), file);
+    this.path = Path.resolve(Path.dirname(options.config.config_path), file);
+    this.slowVerifyMs = config.slow_verify_ms || DEFAULT_SLOW_VERIFY_MS;
   }
 
   /**
    * authenticate - Authenticate user.
    * @param {string} user
    * @param {string} password
-   * @param {function} cd
-   * @returns {function}
+   * @param {function} cb
+   * @returns {void}
    */
   public authenticate(user: string, password: string, cb: Callback): void {
-    this.reload((err) => {
+    this.reload(async (err) => {
       if (err) {
         return cb(err.code === 'ENOENT' ? null : err);
       }
       if (!this.users[user]) {
         return cb(null, false);
       }
-      if (!verifyPassword(password, this.users[user])) {
+
+      let passwordValid = false;
+      try {
+        const start = new Date();
+        passwordValid = await verifyPassword(password, this.users[user]);
+        const durationMs = new Date().getTime() - start.getTime();
+        if (durationMs > this.slowVerifyMs) {
+          this.logger.warn(
+            { user, durationMs },
+            'Password for user "@{user}" took @{durationMs}ms to verify'
+          );
+        }
+      } catch ({ message }) {
+        this.logger.error({ message }, 'Unable to verify user password: @{message}');
+      }
+      if (!passwordValid) {
         return cb(null, false);
       }
 
@@ -130,11 +140,11 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
    * @param {string} user
    * @param {string} password
    * @param {function} realCb
-   * @returns {function}
+   * @returns {Promise<any>}
    */
-  public adduser(user: string, password: string, realCb: Callback): any {
+  public async adduser(user: string, password: string, realCb: Callback): Promise<any> {
     const pathPass = this.path;
-    let sanity = sanityCheck(user, password, verifyPassword, this.users, this.maxUsers);
+    let sanity = await sanityCheck(user, password, verifyPassword, this.users, this.maxUsers);
 
     // preliminary checks, just to ensure that file won't be reloaded if it's
     // not needed
@@ -142,7 +152,7 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
       return realCb(sanity, false);
     }
 
-    lockAndRead(pathPass, (err, res): void => {
+    lockAndRead(pathPass, async (err, res): Promise<void> => {
       let locked = false;
 
       // callback that cleans up lock first
@@ -170,7 +180,7 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
 
       // real checks, to prevent race conditions
       // parsing users after reading file.
-      sanity = sanityCheck(user, password, verifyPassword, this.users, this.maxUsers);
+      sanity = await sanityCheck(user, password, verifyPassword, this.users, this.maxUsers);
 
       if (sanity) {
         return cb(sanity);
@@ -230,7 +240,8 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
    * changePassword - change password for existing user.
    * @param {string} user
    * @param {string} password
-   * @param {function} cd
+   * @param {string} newPassword
+   * @param {function} realCb
    * @returns {function}
    */
   public changePassword(
@@ -239,7 +250,7 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
     newPassword: string,
     realCb: Callback
   ): void {
-    lockAndRead(this.path, (err, res) => {
+    lockAndRead(this.path, async (err, res) => {
       let locked = false;
       const pathPassFile = this.path;
 
@@ -266,13 +277,9 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
       const body = this._stringToUt8(res);
       this.users = parseHTPasswd(body);
 
-      if (!this.users[user]) {
-        return cb(new Error('User not found'));
-      }
-
       try {
         this._writeFile(
-          changePasswordToHTPasswd(body, user, password, newPassword, this.hashConfig),
+          await changePasswordToHTPasswd(body, user, password, newPassword, this.hashConfig),
           cb
         );
       } catch (err: any) {
diff --git a/packages/plugins/htpasswd/src/utils.ts b/packages/plugins/htpasswd/src/utils.ts
index 958b0c6e2..4a78927fc 100644
--- a/packages/plugins/htpasswd/src/utils.ts
+++ b/packages/plugins/htpasswd/src/utils.ts
@@ -39,8 +39,9 @@ export function lockAndRead(name: string, cb: Callback): void {
  * @returns {object}
  */
 export function parseHTPasswd(input: string): Record<string, any> {
-  return input.split('\n').reduce((result, line) => {
-    const args = line.split(':', 3);
+  // The input is split on line ending styles that are both windows and unix compatible
+  return input.split(/[\r]?[\n]/).reduce((result, line) => {
+    const args = line.split(':', 3).map((str) => str.trim());
     if (args.length > 1) {
       result[args[0]] = args[1];
     }
@@ -52,11 +53,13 @@ export function parseHTPasswd(input: string): Record<string, any> {
  * verifyPassword - matches password and it's hash.
  * @param {string} passwd
  * @param {string} hash
- * @returns {boolean}
+ * @returns {Promise<boolean>}
  */
-export function verifyPassword(passwd: string, hash: string): boolean {
-  if (hash.match(/^\$2(a|b|y)\$/)) {
-    return bcrypt.compareSync(passwd, hash);
+export async function verifyPassword(passwd: string, hash: string): Promise<boolean> {
+  if (hash.match(/^\$2([aby])\$/)) {
+    return new Promise((resolve, reject) =>
+      bcrypt.compare(passwd, hash, (error, result) => (error ? reject(error) : resolve(result)))
+    );
   } else if (hash.indexOf('{PLAIN}') === 0) {
     return passwd === hash.substr(7);
   } else if (hash.indexOf('{SHA}') === 0) {
@@ -112,6 +115,7 @@ export function generateHtpasswdLine(
  * @param {string} body
  * @param {string} user
  * @param {string} passwd
+ * @param {HtpasswdHashConfig} hashConfig
  * @returns {string}
  */
 export function addUserToHTPasswd(
@@ -139,16 +143,18 @@ export function addUserToHTPasswd(
  * Sanity check for a user
  * @param {string} user
  * @param {object} users
+ * @param {string} password
+ * @param {Callback} verifyFn
  * @param {number} maxUsers
  * @returns {object}
  */
-export function sanityCheck(
+export async function sanityCheck(
   user: string,
   password: string,
   verifyFn: Callback,
   users: {},
   maxUsers: number
-): HttpError | null {
+): Promise<HttpError | null> {
   let err;
 
   // check for user or password
@@ -167,7 +173,7 @@ export function sanityCheck(
   }
 
   if (hash) {
-    const auth = verifyFn(password, users[user]);
+    const auth = await verifyFn(password, users[user]);
     if (auth) {
       err = Error(API_ERROR.USERNAME_ALREADY_REGISTERED);
       err.status = HTTP_STATUS.CONFLICT;
@@ -191,28 +197,27 @@ export function sanityCheck(
  * @param {string} user
  * @param {string} passwd
  * @param {string} newPasswd
+ * @param {HtpasswdHashConfig} hashConfig
  * @returns {string}
  */
-export function changePasswordToHTPasswd(
+export async function changePasswordToHTPasswd(
   body: string,
   user: string,
   passwd: string,
   newPasswd: string,
   hashConfig: HtpasswdHashConfig
-): string {
+): Promise<string> {
   let lines = body.split('\n');
-  lines = lines.map((line) => {
-    const [username, hash] = line.split(':', 3);
-
-    if (username === user) {
-      if (verifyPassword(passwd, hash)) {
-        line = generateHtpasswdLine(user, newPasswd, hashConfig);
-      } else {
-        throw new Error('Invalid old Password');
-      }
-    }
-    return line;
-  });
-
+  const userLineIndex = lines.findIndex((line) => line.split(':', 1).shift() === user);
+  if (userLineIndex === -1) {
+    throw new Error(`Unable to change password for user '${user}': user does not currently exist`);
+  }
+  const [username, hash] = lines[userLineIndex].split(':', 2);
+  const passwordValid = await verifyPassword(passwd, hash);
+  if (!passwordValid) {
+    throw new Error(`Unable to change password for user '${user}': invalid old password`);
+  }
+  const updatedUserLine = generateHtpasswdLine(username, newPasswd, hashConfig);
+  lines.splice(userLineIndex, 1, updatedUserLine);
   return lines.join('\n');
 }
diff --git a/packages/plugins/htpasswd/tests/__fixtures__/htpasswd b/packages/plugins/htpasswd/tests/__fixtures__/htpasswd
index dda54a931..5c8a14a3f 100644
--- a/packages/plugins/htpasswd/tests/__fixtures__/htpasswd
+++ b/packages/plugins/htpasswd/tests/__fixtures__/htpasswd
@@ -1,2 +1,3 @@
 test:$6FrCaT/v0dwE:autocreated 2018-01-17T03:40:22.958Z
 username:$66to3JK5RgZM:autocreated 2018-01-17T03:40:46.315Z
+bcrypt:$2y$04$K2Cn3StiXx4CnLmcTW/ymekOrj7WlycZZF9xgmoJ/U0zGPqSLPVBe
diff --git a/packages/plugins/htpasswd/tests/__mocks__/Logger.ts b/packages/plugins/htpasswd/tests/__mocks__/Logger.ts
deleted file mode 100644
index 18e0b8c4a..000000000
--- a/packages/plugins/htpasswd/tests/__mocks__/Logger.ts
+++ /dev/null
@@ -1 +0,0 @@
-export default class Logger {}
diff --git a/packages/plugins/htpasswd/tests/htpasswd.test.ts b/packages/plugins/htpasswd/tests/htpasswd.test.ts
index 6f34180ff..50203d7d5 100644
--- a/packages/plugins/htpasswd/tests/htpasswd.test.ts
+++ b/packages/plugins/htpasswd/tests/htpasswd.test.ts
@@ -1,36 +1,35 @@
 /* eslint-disable jest/no-mocks-import */
+// @ts-ignore: Module has no default export
+import bcrypt from 'bcryptjs';
+// @ts-ignore: Module has no default export
 import crypto from 'crypto';
-// @ts-ignore
+// @ts-ignore: Module has no default export
 import fs from 'fs';
 import MockDate from 'mockdate';
 
-import HTPasswd, { VerdaccioConfigApp } from '../src/htpasswd';
+import { PluginOptions } from '@verdaccio/types';
+
+import HTPasswd, { DEFAULT_SLOW_VERIFY_MS, HTPasswdConfig } from '../src/htpasswd';
 import { HtpasswdHashAlgorithm } from '../src/utils';
 import Config from './__mocks__/Config';
-// FIXME: remove this mocks imports
-import Logger from './__mocks__/Logger';
 
-const stuff = {
-  logger: new Logger(),
+const options = {
+  logger: { warn: jest.fn() },
   config: new Config(),
-};
+} as any as PluginOptions<HTPasswdConfig>;
 
 const config = {
   file: './htpasswd',
   max_users: 1000,
-};
-
-const getDefaultConfig = (): VerdaccioConfigApp => ({
-  file: './htpasswd',
-  max_users: 1000,
-});
+} as HTPasswdConfig;
 
 describe('HTPasswd', () => {
   let wrapper;
 
   beforeEach(() => {
-    wrapper = new HTPasswd(getDefaultConfig(), stuff as unknown as VerdaccioConfigApp);
+    wrapper = new HTPasswd(config, options);
     jest.resetModules();
+    jest.clearAllMocks();
 
     crypto.randomBytes = jest.fn(() => {
       return {
@@ -40,46 +39,71 @@ describe('HTPasswd', () => {
   });
 
   describe('constructor()', () => {
-    const emptyPluginOptions = { config: {} } as VerdaccioConfigApp;
+    const emptyPluginOptions = { config: {} } as any as PluginOptions<HTPasswdConfig>;
 
-    test('should files whether file path does not exist', () => {
+    test('should ensure file path configuration exists', () => {
       expect(function () {
-        new HTPasswd({}, emptyPluginOptions);
+        new HTPasswd({} as HTPasswdConfig, emptyPluginOptions);
       }).toThrow(/should specify "file" in config/);
     });
 
     test('should throw error about incorrect algorithm', () => {
       expect(function () {
-        let config = getDefaultConfig();
-        config.algorithm = 'invalid' as any;
-        new HTPasswd(config, emptyPluginOptions);
+        let invalidConfig = { algorithm: 'invalid', ...config } as HTPasswdConfig;
+        new HTPasswd(invalidConfig, emptyPluginOptions);
       }).toThrow(/Invalid algorithm "invalid"/);
     });
   });
 
   describe('authenticate()', () => {
     test('it should authenticate user with given credentials', (done) => {
-      const callbackTest = (a, b): void => {
-        expect(a).toBeNull();
-        expect(b).toContain('test');
-        done();
+      const users = [
+        { username: 'test', password: 'test' },
+        { username: 'username', password: 'password' },
+        { username: 'bcrypt', password: 'password' },
+      ];
+      let usersAuthenticated = 0;
+      const generateCallback = (username) => (error, userGroups) => {
+        usersAuthenticated += 1;
+        expect(error).toBeNull();
+        expect(userGroups).toContain(username);
+        usersAuthenticated === users.length && done();
       };
-      const callbackUsername = (a, b): void => {
-        expect(a).toBeNull();
-        expect(b).toContain('username');
-        done();
-      };
-      wrapper.authenticate('test', 'test', callbackTest);
-      wrapper.authenticate('username', 'password', callbackUsername);
+      users.forEach(({ username, password }) =>
+        wrapper.authenticate(username, password, generateCallback(username))
+      );
     });
 
     test('it should not authenticate user with given credentials', (done) => {
+      const users = ['test', 'username', 'bcrypt'];
+      let usersAuthenticated = 0;
+      const generateCallback = () => (error, userGroups) => {
+        usersAuthenticated += 1;
+        expect(error).toBeNull();
+        expect(userGroups).toBeFalsy();
+        usersAuthenticated === users.length && done();
+      };
+      users.forEach((username) =>
+        wrapper.authenticate(username, 'somerandompassword', generateCallback())
+      );
+    });
+
+    test('it should warn on slow password verification', (done) => {
+      bcrypt.compare = jest.fn((passwd, hash, callback) => {
+        setTimeout(() => callback(null, true), DEFAULT_SLOW_VERIFY_MS + 1);
+      });
       const callback = (a, b): void => {
         expect(a).toBeNull();
-        expect(b).toBeFalsy();
+        expect(b).toContain('bcrypt');
+        const mockWarn = options.logger.warn as jest.MockedFn<jest.MockableFunction>;
+        expect(mockWarn.mock.calls.length).toBe(1);
+        const [{ user, durationMs }, message] = mockWarn.mock.calls[0];
+        expect(user).toEqual('bcrypt');
+        expect(durationMs).toBeGreaterThan(DEFAULT_SLOW_VERIFY_MS);
+        expect(message).toEqual('Password for user "@{user}" took @{durationMs}ms to verify');
         done();
       };
-      wrapper.authenticate('test', 'somerandompassword', callback);
+      wrapper.authenticate('bcrypt', 'password', callback);
     });
   });
 
@@ -122,7 +146,7 @@ describe('HTPasswd', () => {
         });
 
         const HTPasswd = require('../src/htpasswd.ts').default;
-        const wrapper = new HTPasswd(config, stuff);
+        const wrapper = new HTPasswd(config, options);
         wrapper.adduser('sanityCheck', 'test', (sanity) => {
           expect(sanity.message).toBeDefined();
           expect(sanity.message).toMatch('some error');
@@ -140,7 +164,7 @@ describe('HTPasswd', () => {
         });
 
         const HTPasswd = require('../src/htpasswd.ts').default;
-        const wrapper = new HTPasswd(config, stuff);
+        const wrapper = new HTPasswd(config, options);
         wrapper.adduser('lockAndRead', 'test', (sanity) => {
           expect(sanity.message).toBeDefined();
           expect(sanity.message).toMatch('lock error');
@@ -160,7 +184,7 @@ describe('HTPasswd', () => {
         });
 
         const HTPasswd = require('../src/htpasswd.ts').default;
-        const wrapper = new HTPasswd(config, stuff);
+        const wrapper = new HTPasswd(config, options);
         wrapper.adduser('addUserToHTPasswd', 'test', () => {
           done();
         });
@@ -187,7 +211,7 @@ describe('HTPasswd', () => {
         });
 
         const HTPasswd = require('../src/htpasswd.ts').default;
-        const wrapper = new HTPasswd(config, stuff);
+        const wrapper = new HTPasswd(config, options);
         wrapper.adduser('addUserToHTPasswd', 'test', (err) => {
           expect(err).not.toBeNull();
           expect(err.message).toMatch('write error');
@@ -198,7 +222,11 @@ describe('HTPasswd', () => {
 
     describe('reload()', () => {
       test('it should read the file and set the users', (done) => {
-        const output = { test: '$6FrCaT/v0dwE', username: '$66to3JK5RgZM' };
+        const output = {
+          test: '$6FrCaT/v0dwE',
+          username: '$66to3JK5RgZM',
+          bcrypt: '$2y$04$K2Cn3StiXx4CnLmcTW/ymekOrj7WlycZZF9xgmoJ/U0zGPqSLPVBe',
+        };
         const callback = (): void => {
           expect(wrapper.users).toEqual(output);
           done();
@@ -224,7 +252,7 @@ describe('HTPasswd', () => {
         };
 
         const HTPasswd = require('../src/htpasswd.ts').default;
-        const wrapper = new HTPasswd(config, stuff);
+        const wrapper = new HTPasswd(config, options);
         wrapper.reload(callback);
       });
 
@@ -247,7 +275,7 @@ describe('HTPasswd', () => {
         };
 
         const HTPasswd = require('../src/htpasswd.ts').default;
-        const wrapper = new HTPasswd(config, stuff);
+        const wrapper = new HTPasswd(config, options);
         wrapper.reload(callback);
       });
 
@@ -267,7 +295,7 @@ describe('HTPasswd', () => {
         };
 
         const HTPasswd = require('../src/htpasswd.ts').default;
-        const wrapper = new HTPasswd(config, stuff);
+        const wrapper = new HTPasswd(config, options);
         wrapper.reload(callback);
       });
     });
@@ -276,7 +304,9 @@ describe('HTPasswd', () => {
   test('changePassword - it should throw an error for user not found', (done) => {
     const callback = (error, isSuccess): void => {
       expect(error).not.toBeNull();
-      expect(error.message).toBe('User not found');
+      expect(error.message).toBe(
+        `Unable to change password for user 'usernotpresent': user does not currently exist`
+      );
       expect(isSuccess).toBeFalsy();
       done();
     };
@@ -286,7 +316,9 @@ describe('HTPasswd', () => {
   test('changePassword - it should throw an error for wrong password', (done) => {
     const callback = (error, isSuccess): void => {
       expect(error).not.toBeNull();
-      expect(error.message).toBe('Invalid old Password');
+      expect(error.message).toBe(
+        `Unable to change password for user 'username': invalid old password`
+      );
       expect(isSuccess).toBeFalsy();
       done();
     };
diff --git a/packages/plugins/htpasswd/tests/utils.test.ts b/packages/plugins/htpasswd/tests/utils.test.ts
index 11752261f..d6cb0bb86 100644
--- a/packages/plugins/htpasswd/tests/utils.test.ts
+++ b/packages/plugins/htpasswd/tests/utils.test.ts
@@ -1,3 +1,4 @@
+// @ts-ignore: Module has no default export
 import crypto from 'crypto';
 import MockDate from 'mockdate';
 
@@ -66,40 +67,40 @@ user4:$6FrCasdvppdwE:autocreated 2017-12-14T13:30:20.838Z`;
 });
 
 describe('verifyPassword', () => {
-  it('should verify the MD5/Crypt3 password with true', () => {
+  it('should verify the MD5/Crypt3 password with true', async () => {
     const input = ['test', '$apr1$sKXK9.lG$rZ4Iy63Vtn8jF9/USc4BV0'];
-    expect(verifyPassword(input[0], input[1])).toBeTruthy();
+    expect(await verifyPassword(input[0], input[1])).toBeTruthy();
   });
-  it('should verify the MD5/Crypt3 password with false', () => {
+  it('should verify the MD5/Crypt3 password with false', async () => {
     const input = ['testpasswordchanged', '$apr1$sKXK9.lG$rZ4Iy63Vtn8jF9/USc4BV0'];
-    expect(verifyPassword(input[0], input[1])).toBeFalsy();
+    expect(await verifyPassword(input[0], input[1])).toBeFalsy();
   });
-  it('should verify the plain password with true', () => {
+  it('should verify the plain password with true', async () => {
     const input = ['testpasswordchanged', '{PLAIN}testpasswordchanged'];
-    expect(verifyPassword(input[0], input[1])).toBeTruthy();
+    expect(await verifyPassword(input[0], input[1])).toBeTruthy();
   });
-  it('should verify the plain password with false', () => {
+  it('should verify the plain password with false', async () => {
     const input = ['testpassword', '{PLAIN}testpasswordchanged'];
-    expect(verifyPassword(input[0], input[1])).toBeFalsy();
+    expect(await verifyPassword(input[0], input[1])).toBeFalsy();
   });
-  it('should verify the crypto SHA password with true', () => {
+  it('should verify the crypto SHA password with true', async () => {
     const input = ['testpassword', '{SHA}i7YRj4/Wk1rQh2o740pxfTJwj/0='];
-    expect(verifyPassword(input[0], input[1])).toBeTruthy();
+    expect(await verifyPassword(input[0], input[1])).toBeTruthy();
   });
-  it('should verify the crypto SHA password with false', () => {
+  it('should verify the crypto SHA password with false', async () => {
     const input = ['testpasswordchanged', '{SHA}i7YRj4/Wk1rQh2o740pxfTJwj/0='];
-    expect(verifyPassword(input[0], input[1])).toBeFalsy();
+    expect(await verifyPassword(input[0], input[1])).toBeFalsy();
   });
-  it('should verify the bcrypt password with true', () => {
+  it('should verify the bcrypt password with true', async () => {
     const input = ['testpassword', '$2y$04$Wqed4yN0OktGbiUdxSTwtOva1xfESfkNIZfcS9/vmHLsn3.lkFxJO'];
-    expect(verifyPassword(input[0], input[1])).toBeTruthy();
+    expect(await verifyPassword(input[0], input[1])).toBeTruthy();
   });
-  it('should verify the bcrypt password with false', () => {
+  it('should verify the bcrypt password with false', async () => {
     const input = [
       'testpasswordchanged',
       '$2y$04$Wqed4yN0OktGbiUdxSTwtOva1xfESfkNIZfcS9/vmHLsn3.lkFxJO',
     ];
-    expect(verifyPassword(input[0], input[1])).toBeFalsy();
+    expect(await verifyPassword(input[0], input[1])).toBeFalsy();
   });
 });
 
@@ -170,58 +171,58 @@ describe('sanityCheck', () => {
     users = { test: '$6FrCaT/v0dwE' };
   });
 
-  test('should throw error for user already exists', () => {
+  test('should throw error for user already exists', async () => {
     const verifyFn = jest.fn();
-    const input = sanityCheck('test', users.test, verifyFn, users, Infinity);
+    const input = await sanityCheck('test', users.test, verifyFn, users, Infinity);
     expect(input.status).toEqual(401);
     expect(input.message).toEqual('unauthorized access');
     expect(verifyFn).toHaveBeenCalled();
   });
 
-  test('should throw error for registration disabled of users', () => {
+  test('should throw error for registration disabled of users', async () => {
     const verifyFn = (): void => {};
-    const input = sanityCheck('username', users.test, verifyFn, users, -1);
+    const input = await sanityCheck('username', users.test, verifyFn, users, -1);
     expect(input.status).toEqual(409);
     expect(input.message).toEqual('user registration disabled');
   });
 
-  test('should throw error max number of users', () => {
+  test('should throw error max number of users', async () => {
     const verifyFn = (): void => {};
-    const input = sanityCheck('username', users.test, verifyFn, users, 1);
+    const input = await sanityCheck('username', users.test, verifyFn, users, 1);
     expect(input.status).toEqual(403);
     expect(input.message).toEqual('maximum amount of users reached');
   });
 
-  test('should not throw anything and sanity check', () => {
+  test('should not throw anything and sanity check', async () => {
     const verifyFn = (): void => {};
-    const input = sanityCheck('username', users.test, verifyFn, users, 2);
+    const input = await sanityCheck('username', users.test, verifyFn, users, 2);
     expect(input).toBeNull();
   });
 
-  test('should throw error for required username field', () => {
+  test('should throw error for required username field', async () => {
     const verifyFn = (): void => {};
-    const input = sanityCheck(undefined, users.test, verifyFn, users, 2);
+    const input = await sanityCheck(undefined, users.test, verifyFn, users, 2);
     expect(input.message).toEqual('username and password is required');
     expect(input.status).toEqual(400);
   });
 
-  test('should throw error for required password field', () => {
+  test('should throw error for required password field', async () => {
     const verifyFn = (): void => {};
-    const input = sanityCheck('username', undefined, verifyFn, users, 2);
+    const input = await sanityCheck('username', undefined, verifyFn, users, 2);
     expect(input.message).toEqual('username and password is required');
     expect(input.status).toEqual(400);
   });
 
-  test('should throw error for required username & password fields', () => {
+  test('should throw error for required username & password fields', async () => {
     const verifyFn = (): void => {};
-    const input = sanityCheck(undefined, undefined, verifyFn, users, 2);
+    const input = await sanityCheck(undefined, undefined, verifyFn, users, 2);
     expect(input.message).toEqual('username and password is required');
     expect(input.status).toEqual(400);
   });
 
-  test('should throw error for existing username and password', () => {
+  test('should throw error for existing username and password', async () => {
     const verifyFn = jest.fn(() => true);
-    const input = sanityCheck('test', users.test, verifyFn, users, 2);
+    const input = await sanityCheck('test', users.test, verifyFn, users, 2);
     expect(input.status).toEqual(409);
     expect(input.message).toEqual('username is already registered');
     expect(verifyFn).toHaveBeenCalledTimes(1);
@@ -229,9 +230,9 @@ describe('sanityCheck', () => {
 
   test(
     'should throw error for existing username and password with max number ' + 'of users reached',
-    () => {
+    async () => {
       const verifyFn = jest.fn(() => true);
-      const input = sanityCheck('test', users.test, verifyFn, users, 1);
+      const input = await sanityCheck('test', users.test, verifyFn, users, 1);
       expect(input.status).toEqual(409);
       expect(input.message).toEqual('username is already registered');
       expect(verifyFn).toHaveBeenCalledTimes(1);
@@ -240,11 +241,11 @@ describe('sanityCheck', () => {
 });
 
 describe('changePasswordToHTPasswd', () => {
-  test('should throw error for wrong password', () => {
+  test('should throw error for wrong password', async () => {
     const body = 'test:$6b9MlB3WUELU:autocreated 2017-11-06T18:17:21.957Z';
 
     try {
-      changePasswordToHTPasswd(
+      await changePasswordToHTPasswd(
         body,
         'test',
         'somerandompassword',
@@ -252,15 +253,35 @@ describe('changePasswordToHTPasswd', () => {
         defaultHashConfig
       );
     } catch (error: any) {
-      expect(error.message).toEqual('Invalid old Password');
+      expect(error.message).toEqual(
+        `Unable to change password for user 'test': invalid old password`
+      );
     }
   });
 
-  test('should change the password', () => {
+  test('should throw error when user does not exist', async () => {
+    const body = 'test:$6b9MlB3WUELU:autocreated 2017-11-06T18:17:21.957Z';
+
+    try {
+      await changePasswordToHTPasswd(
+        body,
+        'test2',
+        'somerandompassword',
+        'newPassword',
+        defaultHashConfig
+      );
+    } catch (error: any) {
+      expect(error.message).toEqual(
+        `Unable to change password for user 'test2': user does not currently exist`
+      );
+    }
+  });
+
+  test('should change the password', async () => {
     const body = 'root:$6qLTHoPfGLy2:autocreated 2018-08-20T13:38:12.164Z';
 
     expect(
-      changePasswordToHTPasswd(body, 'root', 'demo123', 'newPassword', defaultHashConfig)
+      await changePasswordToHTPasswd(body, 'root', 'demo123', 'newPassword', defaultHashConfig)
     ).toMatchSnapshot();
   });
 });