    function checkPassword($username, $password)
    {
        // Introduce a random delay in case of failures, as recommended by:
        // https://www.owasp.org/index.php/Blocking_Brute_Force_Attacks
        //
        // The base delay is 1-5 seconds.
        $waitMs = mt_rand(1000, 5000);

        $oLock = OA_DB_AdvisoryLock::factory();

        // Username check is case insensitive
        $username = strtolower($username);

        // Try to acquire an excusive advisory lock for the username
        $lock = $oLock->get('auth.'.md5($username));

        if (!$lock) {
            // We couldn't acquire the lock immediately, which means that
            // another authentication process for the same username is underway.
            //
            // This might mean that the account is being targeted by a
            // multi-threaded brute force attack, so we try to discourage such
            // behaviour by increasing the delay time by 4x.
            //
            // However, if the actual user tries to log in while their account
            // is being attacked, we will allow them in, they'd just have to
            // be patient (max 20 seconds).
            usleep($waitMs * 4000);
        }

        $doUser = OA_Dal::factoryDO('users');
        $doUser->username = $username;
        $doUser->password = md5($password);

        $doUser->find();

        if ($doUser->fetch()) {
            $oLock->release();

            return $doUser;
        }

        if ($lock) {
            // The password was wrong, but no other login attempt was in place
            // so we apply just the base delay time.
            usleep($waitMs * 1000);
        }

        $oLock->release();

        return false;
    }
When an actor claims to have a given identity, the software does not prove or insufficiently proves that the claim is correct.