public function authenticate(string $username, string $password): User
    {
        $auth = $this->authenticationProvider->findByUsername($username);
        $user = null;

        if (!$auth && filter_var($username, FILTER_VALIDATE_EMAIL)) {
            if ($user = $this->userProvider->findByEmail($username)) {
                $auth = $this->authenticationProvider->findByUserId($user->getId());
            }
        }

        if (!$auth) {
            throw new NoSuchUserException();
        }

        if (password_verify($password, $auth->getHash())) {

            if (!$user) {
                $user = $this->userProvider->getUser($auth->getUserId());
            }

            if ($user) {
                $this->resetAuthenticationKey($auth);
                $this->setSessionCookies($auth);
                $this->setIdentity($user);

                if (password_needs_rehash($auth->getHash(), PASSWORD_DEFAULT)) {
                    $auth->setHash(password_hash($password, PASSWORD_DEFAULT));
                    $this->authenticationProvider->update($auth);
                }

                return $user;
            } else {
                throw new NoSuchUserException();
            }
        }

        throw new BadPasswordException();
    }