class ExtensionWebSocketClient {

    synchronized public CompletableFuture<Boolean> authenticate(String user, String pass) {
        Map<String, String> authData = new LinkedHashMap<>();
        authData.put("username", user);
        authData.put("password", pass);
        this.authData = authData;

        // Only create the authFuture if there has been no request or a failed request, and a websocket request has 
        // been made
        if (webSocketFuture != null && (authFuture == null || !authFuture.getNow(true))) {
            // Builds a Future that sends an authentication message and waits for the result if the websocket
            // connection succeeded, or is immediately false if the websocket connection failed
            authFuture = webSocketFuture.thenComposeAsync(
                    (wsSuccess) ->
                        {
                            if (wsSuccess) {
                                doAuthentication();
                                return new CompletableFuture<Boolean>();
                            } else {
                                return CompletableFuture.completedFuture(false);
                            }
                        }
                    );
        }
        return authFuture;
    }

    public  ExtensionWebSocketClient(String sourceName);

}