private static MultiSiteOAuth2ClientOptions buildClientOptions(JsonObject config) {
        MultiSiteOAuth2ClientOptions options = new MultiSiteOAuth2ClientOptions(config);
        String authServer = config.getString("auth-server-url");
        String authServerPublic = config.getString("auth-server-public-url"); // We can deprecate this, probably.
        String realmName = config.getString("realm");
        String clientId = config.getString("resource");

        Objects.requireNonNull(authServer, "Must provide auth-server-url");
        Objects.requireNonNull(realmName, "Must provide realm");
        Objects.requireNonNull(clientId, "Must provide resource (also known as Client ID)");

        String defaultSite = buildIssuerWithRealm(authServer, realmName);

        options.setFlow(OAuth2FlowType.PASSWORD);
        options.setSite(defaultSite);
        options.addAllowedIssuer(authServerPublic);
        options.setClientID(clientId);

        // TODO(msavy): this is a total mess, needs redoing to remove all
        // this hacky manual code and document the options that have been added.

        config.getJsonArray("allowed-issuers", new JsonArray())
                .stream()
                .map(Object::toString)
                .filter(s -> !s.isBlank())
                .forEach(allowedIssuer -> options.addAllowedIssuer(buildIssuerWithRealm(allowedIssuer, realmName)));

        if (config.containsKey("credentials") && config.getJsonObject("credentials").containsKey("secret")) {
            options.setClientSecret(config.getJsonObject("credentials").getString("secret"));
        }

        if (config.containsKey("public-client") && config.getBoolean("public-client", false)) {
            options.setUseBasicAuthorizationHeader(true);
        }

        // HTTP Client Options
        if (config.containsKey("ssl-required")) {
            if (!config.getString("ssl-required").equalsIgnoreCase("none")) {
                options.setSsl(true);
            }
        }

        if (config.containsKey("allow-any-hostname")) {
            Object value = config.getValue("allow-any-hostname");
            if (value.equals(true) || value.equals("true")) {
                options.setVerifyHost(false);
            }
        }

        if (config.containsKey("disable-trust-manager")) {
            Object value = config.getValue("disable-trust-manager");
            if (value.equals(true) || value.equals("true")) {
                options.setTrustAll(true);
            }
        }

        if (config.containsKey("truststore") && config.containsKey("truststore-password")) {
            options.setTrustStoreOptions(new JksOptions().setPath(config.getString("truststore")).setPassword(
                    config.getString("truststore-password")));
        }

        if (config.containsKey("client-keystore") && config.containsKey("client-keystore-password")) {
            options.setTrustStoreOptions(new JksOptions().setPath(config.getString("client-keystore")).setPassword(
                    config.getString("client-keystore-password")));
        }

        return options;
    }
@author Marc Savy {@literal <marc@rhymewithgravy.com>}
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/api/auth/KeycloakOAuthFactory.java