public static function refreshToken()
    {
        $token = Session::getSessionToken();
        //-----------------------------------------------------------------
        // This will avoid TokenExpiredException error as long as we are
        // still in the refresh TTL window. Will still allow throwing
        // TokenExpiredException after refresh TTL has passed.
        //
        // NOTE: No tokens (including forever tokens) can ever be
        // refreshed after refresh TTL has passed.
        JWTAuth::manager()->setRefreshFlow();
        //-----------------------------------------------------------------

        try {
            JWTAuth::setToken($token);

            // Checks for token validity - Expired TTL, Expired Refresh TTL, Blacklisted.
            JWTAuth::checkOrFail();

            // Retrieve the 'forever' flag (remember_me flag set to true during login.)
            $payloadArray = JWTAuth::manager()->getJWTProvider()->decode($token);
            $forever = boolval(array_get($payloadArray, 'forever'));
            // Retrieve the user associated with the token
            $userId = array_get($payloadArray, 'user_id');
            /** @var User $user */
            $user = User::find($userId);

            // If token is marked forever then re-issue a new token (not refresh)
            // in order to bump up the refresh TTL for the new token.
            if ($forever) {
                // Clear any existing claims. We will be re-issuing a new token with new claims
                // based on the same user of the original token.
                JWTFactory::claims([]);
                // Re-issue new token.
                Session::setUserInfoWithJWT($user, $forever);
            } else {
                $newToken = JWTAuth::refresh(true);
                JWTAuth::setToken($newToken);
                $payload = JWTAuth::getPayload();
                // Add new token to our token mapping
                static::setTokenMap($payload, $newToken);
                Session::setSessionToken($newToken);
                $userInfo = $user->toArray();
                $userInfo['is_sys_admin'] = $user->is_sys_admin;
                Session::setUserInfo($userInfo);
            }
            // Invalidate and remove from our token mapping
            static::invalidate($token);
        } catch (JWTException $e) {
            throw new UnauthorizedException('Token refresh failed. ' . $e->getMessage());
        }

        return Session::getSessionToken();
    }