keycloak-uncached

Merge pull request #1199 from patriot1burke/master apache

4/29/2015 10:59:50 PM

Changes

pom.xml 5(+5 -0)

services/pom.xml 5(+5 -0)

Details

diff --git a/connections/http-client/pom.xml b/connections/http-client/pom.xml
new file mode 100755
index 0000000..f201569
--- /dev/null
+++ b/connections/http-client/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.2.0.RC1-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-connections-http-client</artifactId>
+    <name>Keycloak Connections Apache HttpClient</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/connections/http-client/src/main/java/org/keycloak/connections/httpclient/DefaultHttpClientFactory.java b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/DefaultHttpClientFactory.java
new file mode 100755
index 0000000..703660f
--- /dev/null
+++ b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/DefaultHttpClientFactory.java
@@ -0,0 +1,139 @@
+package org.keycloak.connections.httpclient;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.EntityBuilder;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.util.EnvUtil;
+import org.keycloak.util.KeystoreUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyStore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class DefaultHttpClientFactory implements HttpClientFactory {
+
+    private static final Logger logger = Logger.getLogger(DefaultHttpClientFactory.class);
+
+    private volatile CloseableHttpClient httpClient;
+
+    @Override
+    public HttpClientProvider create(KeycloakSession session) {
+        return new HttpClientProvider() {
+            @Override
+            public HttpClient getHttpClient() {
+                return httpClient;
+            }
+
+            @Override
+            public void close() {
+
+            }
+
+            @Override
+            public int postText(String uri, String text) throws IOException {
+                HttpPost request = new HttpPost(uri);
+                request.setEntity(EntityBuilder.create().setText(text).setContentType(ContentType.TEXT_PLAIN).build());
+                HttpResponse response = httpClient.execute(request);
+                try {
+                    return response.getStatusLine().getStatusCode();
+                } finally {
+                    HttpEntity entity = response.getEntity();
+                    if (entity != null) {
+                        InputStream is = entity.getContent();
+                        if (is != null) is.close();
+                    }
+
+                }
+            }
+
+            @Override
+            public InputStream get(String uri) throws IOException {
+                HttpGet request = new HttpGet(uri);
+                HttpResponse response = httpClient.execute(request);
+                HttpEntity entity = response.getEntity();
+                if (entity == null) return null;
+                return entity.getContent();
+
+            }
+        };
+    }
+
+    @Override
+    public void close() {
+        try {
+            httpClient.close();
+        } catch (IOException e) {
+
+        }
+    }
+
+    @Override
+    public String getId() {
+        return "default";
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+        long socketTimeout = config.getLong("socket-timeout-millis", -1L);
+        long establishConnectionTimeout = config.getLong("establish-connection-timeout-millis", -1L);
+        int maxPooledPerRoute = config.getInt("max-pooled-per-route", 0);
+        int connectionPoolSize = config.getInt("connection-pool-size", 200);
+        boolean disableTrustManager = config.getBoolean("disable-trust-manager", false);
+        boolean disableCookies = config.getBoolean("disable-cookies", true);
+        String hostnameVerificationPolicy = config.get("hostname-verification-policy", "WILDCARD");
+        HttpClientBuilder.HostnameVerificationPolicy hostnamePolicy = HttpClientBuilder.HostnameVerificationPolicy.valueOf(hostnameVerificationPolicy);
+        String truststore = config.get("truststore");
+        String truststorePassword = config.get("truststore-password");
+        String clientKeystore = config.get("client-keystore");
+        String clientKeystorePassword = config.get("client-keystore-password");
+        String clientPrivateKeyPassword = config.get("client-key-password");
+
+        HttpClientBuilder builder = new HttpClientBuilder();
+        builder.socketTimeout(socketTimeout, TimeUnit.MILLISECONDS)
+               .establishConnectionTimeout(establishConnectionTimeout, TimeUnit.MILLISECONDS)
+                .maxPooledPerRoute(maxPooledPerRoute)
+                .connectionPoolSize(connectionPoolSize)
+                .hostnameVerification(hostnamePolicy)
+                .disableCookies(disableCookies);
+        if (disableTrustManager) builder.disableTrustManager();
+        if (truststore != null) {
+            truststore = EnvUtil.replace(truststore);
+            try {
+                builder.trustStore(KeystoreUtil.loadKeyStore(truststore, truststorePassword));
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to load truststore", e);
+            }
+        }
+        if (clientKeystore != null) {
+            clientKeystore = EnvUtil.replace(clientKeystore);
+            try {
+                KeyStore clientCertKeystore = KeystoreUtil.loadKeyStore(clientKeystore, clientKeystorePassword);
+                builder.keyStore(clientCertKeystore, clientPrivateKeyPassword);
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to load keystore", e);
+            }
+        }
+        httpClient = builder.build();
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+
+
+}
diff --git a/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java
new file mode 100755
index 0000000..7459f4d
--- /dev/null
+++ b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java
@@ -0,0 +1,281 @@
+package org.keycloak.connections.httpclient;
+
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
+import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContexts;
+import org.apache.http.conn.ssl.StrictHostnameVerifier;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Abstraction for creating HttpClients. Allows SSL configuration.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HttpClientBuilder {
+    public static enum HostnameVerificationPolicy {
+        /**
+         * Hostname verification is not done on the server's certificate
+         */
+        ANY,
+        /**
+         * Allows wildcards in subdomain names i.e. *.foo.com
+         */
+        WILDCARD,
+        /**
+         * CN must match hostname connecting to
+         */
+        STRICT
+    }
+
+
+    /**
+     * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+     * @version $Revision: 1 $
+     */
+    private static class PassthroughTrustManager implements X509TrustManager {
+        public void checkClientTrusted(X509Certificate[] chain,
+                                       String authType) throws CertificateException {
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain,
+                                       String authType) throws CertificateException {
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+    }
+
+    protected KeyStore truststore;
+    protected KeyStore clientKeyStore;
+    protected String clientPrivateKeyPassword;
+    protected boolean disableTrustManager;
+    protected HostnameVerificationPolicy policy = HostnameVerificationPolicy.WILDCARD;
+    protected SSLContext sslContext;
+    protected int connectionPoolSize = 100;
+    protected int maxPooledPerRoute = 0;
+    protected long connectionTTL = -1;
+    protected TimeUnit connectionTTLUnit = TimeUnit.MILLISECONDS;
+    protected HostnameVerifier verifier = null;
+    protected long socketTimeout = -1;
+    protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
+    protected long establishConnectionTimeout = -1;
+    protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
+    protected boolean disableCookies = false;
+
+
+    /**
+     * Socket inactivity timeout
+     *
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
+    {
+        this.socketTimeout = timeout;
+        this.socketTimeoutUnits = unit;
+        return this;
+    }
+
+    /**
+     * When trying to make an initial socket connection, what is the timeout?
+     *
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
+    {
+        this.establishConnectionTimeout = timeout;
+        this.establishConnectionTimeoutUnits = unit;
+        return this;
+    }
+
+    public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit) {
+        this.connectionTTL = ttl;
+        this.connectionTTLUnit = unit;
+        return this;
+    }
+
+    public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute) {
+        this.maxPooledPerRoute = maxPooledPerRoute;
+        return this;
+    }
+
+    public HttpClientBuilder connectionPoolSize(int connectionPoolSize) {
+        this.connectionPoolSize = connectionPoolSize;
+        return this;
+    }
+
+    /**
+     * Disable trust management and hostname verification. <i>NOTE</i> this is a security
+     * hole, so only set this option if you cannot or do not want to verify the identity of the
+     * host you are communicating with.
+     */
+    public HttpClientBuilder disableTrustManager() {
+        this.disableTrustManager = true;
+        return this;
+    }
+
+    /**
+     * Disable cookie management.
+     */
+    public HttpClientBuilder disableCookies(boolean disable) {
+        this.disableTrustManager = disable;
+        return this;
+    }
+
+    /**
+     * SSL policy used to verify hostnames
+     *
+     * @param policy
+     * @return
+     */
+    public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy) {
+        this.policy = policy;
+        return this;
+    }
+
+
+    public HttpClientBuilder sslContext(SSLContext sslContext) {
+        this.sslContext = sslContext;
+        return this;
+    }
+
+    public HttpClientBuilder trustStore(KeyStore truststore) {
+        this.truststore = truststore;
+        return this;
+    }
+
+    public HttpClientBuilder keyStore(KeyStore keyStore, String password) {
+        this.clientKeyStore = keyStore;
+        this.clientPrivateKeyPassword = password;
+        return this;
+    }
+
+    public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {
+        this.clientKeyStore = keyStore;
+        this.clientPrivateKeyPassword = new String(password);
+        return this;
+    }
+
+
+    static class VerifierWrapper implements X509HostnameVerifier {
+        protected HostnameVerifier verifier;
+
+        VerifierWrapper(HostnameVerifier verifier) {
+            this.verifier = verifier;
+        }
+
+        @Override
+        public void verify(String host, SSLSocket ssl) throws IOException {
+            if (!verifier.verify(host, ssl.getSession())) throw new SSLException("Hostname verification failure");
+        }
+
+        @Override
+        public void verify(String host, X509Certificate cert) throws SSLException {
+            throw new SSLException("This verification path not implemented");
+        }
+
+        @Override
+        public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
+            throw new SSLException("This verification path not implemented");
+        }
+
+        @Override
+        public boolean verify(String s, SSLSession sslSession) {
+            return verifier.verify(s, sslSession);
+        }
+    }
+
+    public CloseableHttpClient build() {
+        X509HostnameVerifier verifier = null;
+        if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
+        else {
+            switch (policy) {
+                case ANY:
+                    verifier = new AllowAllHostnameVerifier();
+                    break;
+                case WILDCARD:
+                    verifier = new BrowserCompatHostnameVerifier();
+                    break;
+                case STRICT:
+                    verifier = new StrictHostnameVerifier();
+                    break;
+            }
+        }
+        try {
+            SSLConnectionSocketFactory sslsf = null;
+            SSLContext theContext = sslContext;
+            if (disableTrustManager) {
+                theContext = SSLContext.getInstance("TLS");
+                theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
+                        new SecureRandom());
+                verifier = new AllowAllHostnameVerifier();
+                sslsf = new SSLConnectionSocketFactory(theContext, verifier);
+            } else if (theContext != null) {
+                sslsf = new SSLConnectionSocketFactory(theContext, verifier);
+            } else if (clientKeyStore != null || truststore != null) {
+                theContext = createSslContext("TLS", clientKeyStore, clientPrivateKeyPassword, truststore, null);
+                sslsf = new SSLConnectionSocketFactory(theContext, verifier);
+            } else {
+                final SSLContext tlsContext = SSLContext.getInstance("TLS");
+                tlsContext.init(null, null, null);
+                sslsf = new SSLConnectionSocketFactory(tlsContext, verifier);
+            }
+            RequestConfig requestConfig = RequestConfig.custom()
+                    .setConnectTimeout((int) establishConnectionTimeout)
+                    .setSocketTimeout((int) socketTimeout).build();
+
+            org.apache.http.impl.client.HttpClientBuilder builder = HttpClients.custom()
+                    .setDefaultRequestConfig(requestConfig)
+                    .setSSLSocketFactory(sslsf)
+                    .setMaxConnTotal(connectionPoolSize)
+                    .setMaxConnPerRoute(maxPooledPerRoute);
+            if (disableCookies) builder.disableCookieManagement();
+            return builder.build();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private SSLContext createSslContext(
+            final String algorithm,
+            final KeyStore keystore,
+            final String keyPassword,
+            final KeyStore truststore,
+            final SecureRandom random)
+            throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        return SSLContexts.custom()
+                        .useProtocol(algorithm)
+                        .setSecureRandom(random)
+                        .loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null)
+                        .loadTrustMaterial(truststore)
+                        .build();
+    }
+
+}
\ No newline at end of file
diff --git a/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientFactory.java b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientFactory.java
new file mode 100755
index 0000000..2172b4e
--- /dev/null
+++ b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientFactory.java
@@ -0,0 +1,11 @@
+package org.keycloak.connections.httpclient;
+
+import org.apache.http.client.HttpClient;
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface HttpClientFactory extends ProviderFactory<HttpClientProvider> {
+}
diff --git a/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientProvider.java b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientProvider.java
new file mode 100755
index 0000000..d897dd2
--- /dev/null
+++ b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientProvider.java
@@ -0,0 +1,34 @@
+package org.keycloak.connections.httpclient;
+
+import org.apache.http.client.HttpClient;
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface HttpClientProvider extends Provider {
+    HttpClient getHttpClient();
+
+    /**
+     * Helper method
+     *
+     * @param uri
+     * @param text
+     * @return http response status
+     * @throws IOException
+     */
+    public int postText(String uri, String text) throws IOException;
+
+    /**
+     * Helper method
+     *
+     * @param uri
+     * @return response stream, you must close this stream or leaks will happen
+     * @throws IOException
+     */
+    public InputStream get(String uri) throws IOException;
+}
diff --git a/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientSpi.java b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientSpi.java
new file mode 100755
index 0000000..d9f4228
--- /dev/null
+++ b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientSpi.java
@@ -0,0 +1,27 @@
+package org.keycloak.connections.httpclient;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class HttpClientSpi implements Spi {
+
+    @Override
+    public String getName() {
+        return "connectionsHttpClient";
+    }
+
+    @Override
+    public Class<? extends Provider> getProviderClass() {
+        return HttpClientProvider.class;
+    }
+
+    @Override
+    public Class<? extends ProviderFactory> getProviderFactoryClass() {
+        return HttpClientFactory.class;
+    }
+
+}
diff --git a/connections/http-client/src/main/resources/META-INF/services/org.keycloak.connections.httpclient.HttpClientFactory b/connections/http-client/src/main/resources/META-INF/services/org.keycloak.connections.httpclient.HttpClientFactory
new file mode 100755
index 0000000..48a5870
--- /dev/null
+++ b/connections/http-client/src/main/resources/META-INF/services/org.keycloak.connections.httpclient.HttpClientFactory
@@ -0,0 +1 @@
+org.keycloak.connections.httpclient.DefaultHttpClientFactory
\ No newline at end of file
diff --git a/connections/http-client/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/connections/http-client/src/main/resources/META-INF/services/org.keycloak.provider.Spi
new file mode 100755
index 0000000..d91ed39
--- /dev/null
+++ b/connections/http-client/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -0,0 +1 @@
+org.keycloak.connections.httpclient.HttpClientSpi
diff --git a/connections/pom.xml b/connections/pom.xml
index 4e10210..b701354 100755
--- a/connections/pom.xml
+++ b/connections/pom.xml
@@ -19,6 +19,7 @@
         <module>mongo</module>
         <module>file</module>
         <module>mongo-update</module>
+        <module>http-client</module>
     </modules>
 
     <build>
diff --git a/dependencies/server-min/pom.xml b/dependencies/server-min/pom.xml
index aa886a6..0165e72 100755
--- a/dependencies/server-min/pom.xml
+++ b/dependencies/server-min/pom.xml
@@ -135,6 +135,11 @@
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-export-import-single-file</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-http-client</artifactId>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/distribution/modules/build.xml b/distribution/modules/build.xml
index 84c3ead..0fdcfa4 100755
--- a/distribution/modules/build.xml
+++ b/distribution/modules/build.xml
@@ -169,6 +169,10 @@
 
         <!-- server all dependencies -->
 
+        <module-def name="org.keycloak.keycloak-connections-http-client">
+            <maven-resource group="org.keycloak" artifact="keycloak-connections-http-client"/>
+        </module-def>
+
         <module-def name="org.keycloak.keycloak-connections-jpa">
             <maven-resource group="org.keycloak" artifact="keycloak-connections-jpa"/>
         </module-def>
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-connections-http-client/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-connections-http-client/main/module.xml
new file mode 100755
index 0000000..1d35246
--- /dev/null
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-connections-http-client/main/module.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+
+<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-connections-http-client">
+    <resources>
+        <!-- Insert resources here -->
+    </resources>
+    <exports>
+        <include path="META-INF/**"/>
+    </exports>
+    <dependencies>
+        <module name="org.keycloak.keycloak-core"/>
+        <module name="org.keycloak.keycloak-model-api"/>
+        <module name="org.jboss.logging"/>
+        <module name="javax.api"/>
+        <module name="org.apache.httpcomponents" slot="4.3" />
+    </dependencies>
+
+</module>
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-saml-protocol/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-saml-protocol/main/module.xml
index b49da9a..655a8c0 100755
--- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-saml-protocol/main/module.xml
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-saml-protocol/main/module.xml
@@ -21,6 +21,7 @@
         <module name="javax.ws.rs.api"/>
         <module name="org.jboss.resteasy.resteasy-jaxrs"/>
         <module name="org.jboss.resteasy.resteasy-multipart-provider"/>
+        <module name="org.keycloak.keycloak-connections-http-client" services="import"/>
 
         <module name="javax.api"/>
     </dependencies>
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml
index aa75112..55a5518 100755
--- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml
@@ -14,6 +14,7 @@
         <module name="org.keycloak.keycloak-broker-saml" services="import"/>
         <module name="org.keycloak.keycloak-connections-infinispan" services="import"/>
         <module name="org.keycloak.keycloak-connections-jpa" services="import"/>
+        <module name="org.keycloak.keycloak-connections-http-client" services="import"/>
         <module name="org.keycloak.keycloak-connections-jpa-liquibase" services="import"/>
         <module name="org.keycloak.keycloak-connections-mongo" services="import"/>
         <module name="org.keycloak.keycloak-connections-mongo-update" services="import"/>
diff --git a/distribution/subsystem-war/src/main/resources/META-INF/keycloak-server.json b/distribution/subsystem-war/src/main/resources/META-INF/keycloak-server.json
index 9f0d03e..3e1896c 100755
--- a/distribution/subsystem-war/src/main/resources/META-INF/keycloak-server.json
+++ b/distribution/subsystem-war/src/main/resources/META-INF/keycloak-server.json
@@ -63,6 +63,12 @@
         "interval": 900
     },
 
+    "connectionsHttpClient": {
+        "default": {
+            "disable-trust-manager": true
+        }
+    },
+
     "connectionsJpa": {
         "default": {
             "dataSource": "java:jboss/datasources/KeycloakDS",
diff --git a/docbook/reference/en/en-US/modules/server-installation.xml b/docbook/reference/en/en-US/modules/server-installation.xml
index 5b4b043..0c419b7 100755
--- a/docbook/reference/en/en-US/modules/server-installation.xml
+++ b/docbook/reference/en/en-US/modules/server-installation.xml
@@ -395,6 +395,150 @@ All configuration options are optional. Default value for directory is <literal>
             </para>
         </section>
 
+        <section>
+            <title>Outgoing Server HTTP Requests</title>
+            <para>
+                Keycloak server needs to invoke on remote HTTP endpoints to do things like backchannel logouts and other
+                management functions.  Keycloak maintains a HTTP client connection pool which has various configuration
+                settings you can specify before boot time.  This is configured in the
+                <literal>standalone/configuration/keycloak-server.json</literal>.
+                By default the setting is like this:
+                <programlisting><![CDATA[
+    "connectionsHttpClient": {
+        "default": {
+            "disable-trust-manager": true
+        }
+    },
+]]></programlisting>
+                Possible configuration options are:
+                <variablelist>
+                    <varlistentry>
+                        <term>establish-connection-timeout-millis</term>
+                        <listitem>
+                            <para>
+                                Timeout for establishing a socket connection.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>socket-timeout-millis</term>
+                        <listitem>
+                            <para>
+                                If an outgoing request does not receive data for this amount of time, timeout the connection.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>connection-pool-size</term>
+                        <listitem>
+                            <para>
+                                How many connections can be in the pool.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>max-pooled-per-route</term>
+                        <listitem>
+                            <para>
+                                How many connections can be pooled per host.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>disable-trust-manager</term>
+                        <listitem>
+                            <para>
+                                If true, HTTPS server certificates are not verified.  If you set this to false, you must
+                                configure a truststore.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>disable-cookies</term>
+                        <listitem>
+                            <para>
+                                <literal>true</literal> by default.  When set to true, this will disable any cookie
+                                caching.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>hostname-verification-policy</term>
+                        <listitem>
+                            <para>
+                                <literal>WILDCARD</literal> by default.  For HTTPS requests, this verifies the hostname
+                                of the server's certificate.  <literal>ANY</literal> means that the hostname is not verified.
+                                <literal>WILDCARD</literal> Allows wildcards in subdomain names i.e. *.foo.com.
+                                <literal>STRICT</literal> CN must match hostname exactly.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>truststore</term>
+                        <listitem>
+                            <para>
+                                The value is the file path to a Java keystore file.  If
+                                you prefix the path with <literal>classpath:</literal>, then the truststore will be obtained
+                                from the deployment's classpath instead.
+                                HTTPS
+                                requests need a way to verify the host of the server they are talking to. This is
+                                what the trustore does. The keystore contains one or more trusted
+                                host certificates or certificate authorities.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>truststore-password</term>
+                        <listitem>
+                            <para>
+                                Password for the truststore keystore.
+                                This is
+                                <emphasis>REQUIRED</emphasis>
+                                if
+                                <literal>truststore</literal>
+                                is set.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>client-keystore</term>
+                        <listitem>
+                            <para>
+                                This is the file path to a Java keystore file.
+                                This keystore contains client certificate for two-way SSL.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>client-keystore-password</term>
+                        <listitem>
+                            <para>
+                                Password for the client keystore.
+                                This is
+                                <emphasis>REQUIRED</emphasis>
+                                if
+                                <literal>client-keystore</literal>
+                                is set.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>client-key-password</term>
+                        <listitem>
+                            <para>
+                                <emphasis>Not supported yet, but we will support in future versions.</emphasis>
+                                Password for the client's key.
+                                This is
+                                <emphasis>REQUIRED</emphasis>
+                                if
+                                <literal>client-keystore</literal>
+                                is set.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                </variablelist>
+            </para>
+        </section>
         <section id="ssl_modes">
             <title>SSL/HTTPS Requirement/Modes</title>
             <warning>
diff --git a/examples/broker/facebook-authentication/pom.xml b/examples/broker/facebook-authentication/pom.xml
index f6884d5..c089835 100755
--- a/examples/broker/facebook-authentication/pom.xml
+++ b/examples/broker/facebook-authentication/pom.xml
@@ -4,7 +4,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <artifactId>keycloak-examples-broker-parent</artifactId>
+        <artifactId>keycloak-examples-parent</artifactId>
         <groupId>org.keycloak</groupId>
         <version>1.2.0.RC1-SNAPSHOT</version>
     </parent>
diff --git a/examples/broker/google-authentication/pom.xml b/examples/broker/google-authentication/pom.xml
index 6060f3d..1ca7ced 100755
--- a/examples/broker/google-authentication/pom.xml
+++ b/examples/broker/google-authentication/pom.xml
@@ -4,7 +4,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <artifactId>keycloak-examples-broker-parent</artifactId>
+        <artifactId>keycloak-examples-parent</artifactId>
         <groupId>org.keycloak</groupId>
         <version>1.2.0.RC1-SNAPSHOT</version>
     </parent>
diff --git a/examples/broker/saml-broker-authentication/pom.xml b/examples/broker/saml-broker-authentication/pom.xml
index e3945f5..7318e93 100755
--- a/examples/broker/saml-broker-authentication/pom.xml
+++ b/examples/broker/saml-broker-authentication/pom.xml
@@ -4,7 +4,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <artifactId>keycloak-examples-broker-parent</artifactId>
+        <artifactId>keycloak-examples-parent</artifactId>
         <groupId>org.keycloak</groupId>
         <version>1.2.0.RC1-SNAPSHOT</version>
     </parent>
diff --git a/examples/broker/twitter-authentication/pom.xml b/examples/broker/twitter-authentication/pom.xml
index 3e730b7..1e4d425 100755
--- a/examples/broker/twitter-authentication/pom.xml
+++ b/examples/broker/twitter-authentication/pom.xml
@@ -4,7 +4,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <artifactId>keycloak-examples-broker-parent</artifactId>
+        <artifactId>keycloak-examples-parent</artifactId>
         <groupId>org.keycloak</groupId>
         <version>1.2.0.RC1-SNAPSHOT</version>
     </parent>
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
old mode 100644
new mode 100755
index 5999681..d99be80
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
@@ -138,6 +138,7 @@ failedToProcessResponseMessage=Konnte Response nicht verarbeiten.
 httpsRequiredMessage=HTTPS erforderlich.
 realmNotEnabledMessage=Realm nicht aktiviert.
 invalidRequestMessage=Ung\u00FCltiger Request.
+failedLogout=Logout failed
 unknownLoginRequesterMessage=Ung\u00FCltiger login requester
 loginRequesterNotEnabledMessage=Login requester nicht aktiviert.
 bearerOnlyMessage=Bearer-only Applikationen k\u00F6nne sich nicht via Browser anmelden.
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
index 98985ca..9ee2d07 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -140,6 +140,7 @@ failedToProcessResponseMessage=Failed to process response
 httpsRequiredMessage=HTTPS required
 realmNotEnabledMessage=Realm not enabled
 invalidRequestMessage=Invalid Request
+failedLogout=Logout failed
 unknownLoginRequesterMessage=Unknown login requester
 loginRequesterNotEnabledMessage=Login requester not enabled
 bearerOnlyMessage=Bearer-only applications are not allowed to initiate browser login
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties
index b019d6c..8f7be07 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties
@@ -135,6 +135,7 @@ failedToProcessResponseMessage=Fallimento nell''elaborazione della risposta
 httpsRequiredMessage=HTTPS richiesto
 realmNotEnabledMessage=Realm non abilitato
 invalidRequestMessage=Richiesta non valida
+failedLogout=Logout failed
 unknownLoginRequesterMessage=Richiedente di Login non riconosciuto
 loginRequesterNotEnabledMessage=Richiedente di Login non abilitato
 bearerOnlyMessage=Alle applicazioni di tipo Bearer-only non e'' consentito di effettuare il login tramite browser
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties
old mode 100644
new mode 100755
index 8d50d3e..45b4489
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties
@@ -135,6 +135,7 @@ failedToProcessResponseMessage=Falha ao processar a resposta
 httpsRequiredMessage=HTTPS requerido
 realmNotEnabledMessage=Realm desativado
 invalidRequestMessage=Pedido inv\u00E1lido
+failedLogout=Logout failed
 unknownLoginRequesterMessage=Solicitante de login desconhecido
 loginRequesterNotEnabledMessage=Solicitante de login desativado
 bearerOnlyMessage=Aplica\u00E7\u00F5es somente ao portador n\u00E3o tem permiss\u00E3o para iniciar o login pelo navegador
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/jaas/AbstractKeycloakLoginModule.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/jaas/AbstractKeycloakLoginModule.java
old mode 100644
new mode 100755
index 5b6c55d..152a9d8
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/jaas/AbstractKeycloakLoginModule.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/jaas/AbstractKeycloakLoginModule.java
@@ -24,7 +24,7 @@ import org.keycloak.RSATokenVerifier;
 import org.keycloak.VerificationException;
 import org.keycloak.adapters.AdapterDeploymentContext;
 import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.adapters.FindFile;
+import org.keycloak.util.FindFile;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.KeycloakDeploymentBuilder;
 import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
diff --git a/integration/wildfly-extensions/pom.xml b/integration/wildfly-extensions/pom.xml
index 201db70..bb575aa 100755
--- a/integration/wildfly-extensions/pom.xml
+++ b/integration/wildfly-extensions/pom.xml
@@ -37,6 +37,11 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-model-api</artifactId>
             <scope>provided</scope>
         </dependency>

pom.xml 5(+5 -0)

diff --git a/pom.xml b/pom.xml
index 0f15f12..2c97592 100755
--- a/pom.xml
+++ b/pom.xml
@@ -559,6 +559,11 @@
             </dependency>
             <dependency>
                 <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-connections-http-client</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
                 <artifactId>keycloak-connections-mongo-update</artifactId>
                 <version>${project.version}</version>
             </dependency>
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java
index 59977e6..49aed7a 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java
@@ -3,7 +3,6 @@ package org.keycloak.proxy;
 import io.undertow.Undertow;
 import io.undertow.security.api.AuthenticationMechanism;
 import io.undertow.security.api.AuthenticationMode;
-import io.undertow.security.handlers.AuthenticationCallHandler;
 import io.undertow.security.handlers.AuthenticationMechanismsHandler;
 import io.undertow.security.handlers.SecurityInitialHandler;
 import io.undertow.security.idm.Account;
@@ -24,7 +23,7 @@ import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.jboss.logging.Logger;
 import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.FindFile;
+import org.keycloak.util.FindFile;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.KeycloakDeploymentBuilder;
 import org.keycloak.adapters.NodesRegistrationManagement;
@@ -35,7 +34,6 @@ import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
 import org.keycloak.enums.SslRequired;
 import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.util.CertificateUtils;
-import org.keycloak.util.PemUtils;
 import org.keycloak.util.SystemPropertiesJsonParserFactory;
 import org.xnio.Option;
 
diff --git a/saml/saml-protocol/pom.xml b/saml/saml-protocol/pom.xml
index 702be9d..8c2e43a 100755
--- a/saml/saml-protocol/pom.xml
+++ b/saml/saml-protocol/pom.xml
@@ -35,6 +35,11 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-http-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-services</artifactId>
             <scope>provided</scope>
         </dependency>
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index f650b64..9db48d1 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -1,9 +1,14 @@
 package org.keycloak.protocol.saml;
 
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.message.BasicNameValuePair;
 import org.jboss.logging.Logger;
-import org.jboss.resteasy.client.ClientRequest;
-import org.jboss.resteasy.client.ClientResponse;
-import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
+import org.keycloak.connections.httpclient.HttpClientProvider;
 import org.keycloak.dom.saml.v2.assertion.AssertionType;
 import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
 import org.keycloak.dom.saml.v2.protocol.ResponseType;
@@ -37,7 +42,9 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.io.IOException;
+import java.io.InputStream;
 import java.security.PublicKey;
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
@@ -464,6 +471,11 @@ public class SamlProtocol implements LoginProtocol {
     public Response finishLogout(UserSessionModel userSession) {
         logger.debug("finishLogout");
         String logoutBindingUri = userSession.getNote(SAML_LOGOUT_BINDING_URI);
+        if (logoutBindingUri == null) {
+            logger.error("Can't finish SAML logout as there is no logout binding set");
+            return ErrorPage.error(session, Messages.FAILED_LOGOUT);
+
+        }
         String logoutRelayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE);
         SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
         builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID));
@@ -515,35 +527,38 @@ public class SamlProtocol implements LoginProtocol {
         }
 
 
-        ApacheHttpClient4Executor executor = ResourceAdminManager.createExecutor();
-
-
-        try {
-            ClientRequest request = executor.createRequest(logoutUrl);
-            request.formParameter(GeneralConstants.SAML_REQUEST_KEY, logoutRequestString);
-            request.formParameter("BACK_CHANNEL_LOGOUT", "BACK_CHANNEL_LOGOUT"); // for Picketlink adapter, todo remove this
-            ClientResponse response = null;
+        HttpClient httpClient = session.getProvider(HttpClientProvider.class).getHttpClient();
+        for (int i = 0; i < 2; i++) { // follow redirects once
             try {
-                response = request.post();
-                response.releaseConnection();
-                // Undertow will redirect root urls not ending in "/" to root url + "/".  Test for this weird behavior
-                if (response.getStatus() == 302  && !logoutUrl.endsWith("/")) {
-                    String redirect = (String)response.getHeaders().getFirst(HttpHeaders.LOCATION);
-                    String withSlash = logoutUrl + "/";
-                    if (withSlash.equals(redirect)) {
-                        request = executor.createRequest(withSlash);
-                        request.formParameter(GeneralConstants.SAML_REQUEST_KEY, logoutRequestString);
-                        request.formParameter("BACK_CHANNEL_LOGOUT", "BACK_CHANNEL_LOGOUT"); // for Picketlink adapter, todo remove this
-                        response = request.post();
-                        response.releaseConnection();
+                List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+                formparams.add(new BasicNameValuePair(GeneralConstants.SAML_REQUEST_KEY, logoutRequestString));
+                formparams.add(new BasicNameValuePair("BACK_CHANNEL_LOGOUT", "BACK_CHANNEL_LOGOUT")); // for Picketlink todo remove this
+                UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+                HttpPost post = new HttpPost(logoutUrl);
+                post.setEntity(form);
+                HttpResponse response = httpClient.execute(post);
+                try {
+                    int status = response.getStatusLine().getStatusCode();
+                    if (status == 302  && !logoutUrl.endsWith("/")) {
+                        String redirect = response.getFirstHeader(HttpHeaders.LOCATION).getValue();
+                        String withSlash = logoutUrl + "/";
+                        if (withSlash.equals(redirect)) {
+                            logoutUrl = withSlash;
+                            continue;
+                        }
                     }
+                } finally {
+                    HttpEntity entity = response.getEntity();
+                    if (entity != null) {
+                        InputStream is = entity.getContent();
+                        if (is != null) is.close();
+                    }
+
                 }
-            } catch (Exception e) {
+            } catch (IOException e) {
                 logger.warn("failed to send saml logout", e);
             }
-
-        } finally {
-            executor.getHttpClient().getConnectionManager().shutdown();
+            break;
         }
 
     }

services/pom.xml 5(+5 -0)

diff --git a/services/pom.xml b/services/pom.xml
index 2fa148d..3e85216 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -36,6 +36,11 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-http-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-forms-common-freemarker</artifactId>
             <scope>provided</scope>
         </dependency>
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
index 06eefe0..b7c7381 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -22,7 +22,6 @@
 package org.keycloak.protocol.oidc;
 
 import org.jboss.logging.Logger;
-import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.events.Details;
 import org.keycloak.events.EventBuilder;
@@ -166,14 +165,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
     public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
         if (!(clientSession.getClient() instanceof ClientModel)) return;
         ClientModel app = clientSession.getClient();
-        // TODO: Probably non-effective to build executor every time from scratch. Should be likely shared for whole OIDCLoginProtocolFactory
-        ApacheHttpClient4Executor executor = ResourceAdminManager.createExecutor();
-
-        try {
-            new ResourceAdminManager().logoutClientSession(uriInfo.getRequestUri(), realm, app, clientSession, executor);
-        } finally {
-            executor.getHttpClient().getConnectionManager().shutdown();
-        }
+        new ResourceAdminManager(session).logoutClientSession(uriInfo.getRequestUri(), realm, app, clientSession);
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
index ac64cbc..dc0b6a4 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -1,11 +1,8 @@
 package org.keycloak.services.managers;
 
-import org.apache.http.client.HttpClient;
 import org.jboss.logging.Logger;
-import org.jboss.resteasy.client.ClientRequest;
-import org.jboss.resteasy.client.ClientResponse;
-import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
 import org.keycloak.TokenIdGenerator;
+import org.keycloak.connections.httpclient.HttpClientProvider;
 import org.keycloak.constants.AdapterConstants;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
@@ -18,15 +15,14 @@ import org.keycloak.representations.adapters.action.GlobalRequestResult;
 import org.keycloak.representations.adapters.action.LogoutAction;
 import org.keycloak.representations.adapters.action.PushNotBeforeAction;
 import org.keycloak.representations.adapters.action.TestAvailabilityAction;
-import org.keycloak.services.util.HttpClientBuilder;
 import org.keycloak.services.util.ResolveRelative;
 import org.keycloak.util.KeycloakUriBuilder;
 import org.keycloak.util.MultivaluedHashMap;
 import org.keycloak.util.StringPropertyReplacer;
 import org.keycloak.util.Time;
 
-import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.UriBuilder;
+import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -44,11 +40,10 @@ public class ResourceAdminManager {
     protected static Logger logger = Logger.getLogger(ResourceAdminManager.class);
     private static final String CLIENT_SESSION_HOST_PROPERTY = "${application.session.host}";
 
-    public static ApacheHttpClient4Executor createExecutor() {
-        HttpClient client = new HttpClientBuilder()
-                .disableTrustManager() // todo fix this, should have a trust manager or a good default
-                .build();
-        return new ApacheHttpClient4Executor(client);
+    private KeycloakSession session;
+
+    public ResourceAdminManager(KeycloakSession session) {
+        this.session = session;
     }
 
     public static String resolveUri(URI requestUri, String uri) {
@@ -101,23 +96,17 @@ public class ResourceAdminManager {
     }
 
     protected void logoutUserSessions(URI requestUri, RealmModel realm, List<UserSessionModel> userSessions) {
-        ApacheHttpClient4Executor executor = createExecutor();
-
-        try {
-            // Map from "app" to clientSessions for this app
-            MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
-            for (UserSessionModel userSession : userSessions) {
-                putClientSessions(clientSessions, userSession);
-            }
+        // Map from "app" to clientSessions for this app
+        MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
+        for (UserSessionModel userSession : userSessions) {
+            putClientSessions(clientSessions, userSession);
+        }
 
-            logger.debugv("logging out {0} resources ", clientSessions.size());
-            //logger.infov("logging out resources: {0}", clientSessions);
+        logger.debugv("logging out {0} resources ", clientSessions.size());
+        //logger.infov("logging out resources: {0}", clientSessions);
 
-            for (Map.Entry<ClientModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
-                logoutClientSessions(requestUri, realm, entry.getKey(), entry.getValue(), executor);
-            }
-        } finally {
-            executor.getHttpClient().getConnectionManager().shutdown();
+        for (Map.Entry<ClientModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
+            logoutClientSessions(requestUri, realm, entry.getKey(), entry.getValue());
         }
     }
 
@@ -128,32 +117,25 @@ public class ResourceAdminManager {
         }
     }
 
-    public void logoutUserFromClient(URI requestUri, RealmModel realm, ClientModel resource, UserModel user, KeycloakSession session) {
-        ApacheHttpClient4Executor executor = createExecutor();
-
-        try {
-            List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
-            List<ClientSessionModel> ourAppClientSessions = null;
-            if (userSessions != null) {
-                MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
-                for (UserSessionModel userSession : userSessions) {
-                    putClientSessions(clientSessions, userSession);
-                }
-                ourAppClientSessions = clientSessions.get(resource);
+    public void logoutUserFromClient(URI requestUri, RealmModel realm, ClientModel resource, UserModel user) {
+        List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
+        List<ClientSessionModel> ourAppClientSessions = null;
+        if (userSessions != null) {
+            MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
+            for (UserSessionModel userSession : userSessions) {
+                putClientSessions(clientSessions, userSession);
             }
-
-            logoutClientSessions(requestUri, realm, resource, ourAppClientSessions, executor);
-        } finally {
-            executor.getHttpClient().getConnectionManager().shutdown();
+            ourAppClientSessions = clientSessions.get(resource);
         }
 
+        logoutClientSessions(requestUri, realm, resource, ourAppClientSessions);
     }
 
-    public boolean logoutClientSession(URI requestUri, RealmModel realm, ClientModel resource, ClientSessionModel clientSession, ApacheHttpClient4Executor client) {
-        return logoutClientSessions(requestUri, realm, resource, Arrays.asList(clientSession), client);
+    public boolean logoutClientSession(URI requestUri, RealmModel realm, ClientModel resource, ClientSessionModel clientSession) {
+        return logoutClientSessions(requestUri, realm, resource, Arrays.asList(clientSession));
     }
 
-    protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ClientModel resource, List<ClientSessionModel> clientSessions, ApacheHttpClient4Executor client) {
+    protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ClientModel resource, List<ClientSessionModel> clientSessions) {
         String managementUrl = getManagementUrl(requestUri, resource);
         if (managementUrl != null) {
 
@@ -184,7 +166,7 @@ public class ResourceAdminManager {
                     String host = entry.getKey();
                     List<String> sessionIds = entry.getValue();
                     String currentHostMgmtUrl = managementUrl.replace(CLIENT_SESSION_HOST_PROPERTY, host);
-                    allPassed = sendLogoutRequest(realm, resource, sessionIds, userSessions, client, 0, currentHostMgmtUrl) && allPassed;
+                    allPassed = sendLogoutRequest(realm, resource, sessionIds, userSessions, 0, currentHostMgmtUrl) && allPassed;
                 }
 
                 return allPassed;
@@ -195,7 +177,7 @@ public class ResourceAdminManager {
                     allSessionIds.addAll(currentIds);
                 }
 
-                return sendLogoutRequest(realm, resource, allSessionIds, userSessions, client, 0, managementUrl);
+                return sendLogoutRequest(realm, resource, allSessionIds, userSessions, 0, managementUrl);
             }
         } else {
             logger.debugv("Can't logout {0}: no management url", resource.getClientId());
@@ -206,36 +188,25 @@ public class ResourceAdminManager {
     // Methods for logout all
 
     public GlobalRequestResult logoutAll(URI requestUri, RealmModel realm) {
-        ApacheHttpClient4Executor executor = createExecutor();
-
-        try {
-            realm.setNotBefore(Time.currentTime());
-            List<ClientModel> resources = realm.getClients();
-            logger.debugv("logging out {0} resources ", resources.size());
-
-            GlobalRequestResult finalResult = new GlobalRequestResult();
-            for (ClientModel resource : resources) {
-                GlobalRequestResult currentResult = logoutClient(requestUri, realm, resource, executor, realm.getNotBefore());
-                finalResult.addAll(currentResult);
-            }
-            return finalResult;
-        } finally {
-            executor.getHttpClient().getConnectionManager().shutdown();
+        realm.setNotBefore(Time.currentTime());
+        List<ClientModel> resources = realm.getClients();
+        logger.debugv("logging out {0} resources ", resources.size());
+
+        GlobalRequestResult finalResult = new GlobalRequestResult();
+        for (ClientModel resource : resources) {
+            GlobalRequestResult currentResult = logoutClient(requestUri, realm, resource, realm.getNotBefore());
+            finalResult.addAll(currentResult);
         }
+        return finalResult;
     }
 
     public GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource) {
-        ApacheHttpClient4Executor executor = createExecutor();
-        try {
-            resource.setNotBefore(Time.currentTime());
-            return logoutClient(requestUri, realm, resource, executor, resource.getNotBefore());
-        } finally {
-            executor.getHttpClient().getConnectionManager().shutdown();
-        }
+        resource.setNotBefore(Time.currentTime());
+        return logoutClient(requestUri, realm, resource, resource.getNotBefore());
     }
 
 
-    protected GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource, ApacheHttpClient4Executor executor, int notBefore) {
+    protected GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource, int notBefore) {
         List<String> mgmtUrls = getAllManagementUrls(requestUri, resource);
         if (mgmtUrls.isEmpty()) {
             logger.debug("No management URL or no registered cluster nodes for the client " + resource.getClientId());
@@ -247,7 +218,7 @@ public class ResourceAdminManager {
         // Propagate this to all hosts
         GlobalRequestResult result = new GlobalRequestResult();
         for (String mgmtUrl : mgmtUrls) {
-            if (sendLogoutRequest(realm, resource, null, null, executor, notBefore, mgmtUrl)) {
+            if (sendLogoutRequest(realm, resource, null, null, notBefore, mgmtUrl)) {
                 result.addSuccessRequest(mgmtUrl);
             } else {
                 result.addFailedRequest(mgmtUrl);
@@ -256,54 +227,37 @@ public class ResourceAdminManager {
         return result;
     }
 
-    protected boolean sendLogoutRequest(RealmModel realm, ClientModel resource, List<String> adapterSessionIds, List<String> userSessions, ApacheHttpClient4Executor client, int notBefore, String managementUrl) {
+    protected boolean sendLogoutRequest(RealmModel realm, ClientModel resource, List<String> adapterSessionIds, List<String> userSessions, int notBefore, String managementUrl) {
         LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), adapterSessionIds, notBefore, userSessions);
         String token = new TokenManager().encodeToken(realm, adminAction);
         if (logger.isDebugEnabled()) logger.debugv("logout resource {0} url: {1} sessionIds: " + adapterSessionIds, resource.getClientId(), managementUrl);
-        ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_LOGOUT).build().toString());
-        ClientResponse response;
-        try {
-            response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post();
-        } catch (Exception e) {
-            logger.warn("Logout for client '" + resource.getClientId() + "' failed", e);
-            return false;
-        }
+        URI target = UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_LOGOUT).build();
         try {
-            boolean success = response.getStatus() == 204 || response.getStatus() == 200;
+            int status = session.getProvider(HttpClientProvider.class).postText(target.toString(), token);
+            boolean success = status == 204 || status == 200;
             logger.debugf("logout success for %s: %s", managementUrl, success);
             return success;
-        } finally {
-            response.releaseConnection();
+        } catch (IOException e) {
+            logger.warn("Logout for client '" + resource.getClientId() + "' failed", e);
+            return false;
         }
     }
 
     public GlobalRequestResult pushRealmRevocationPolicy(URI requestUri, RealmModel realm) {
-        ApacheHttpClient4Executor executor = createExecutor();
-
-        try {
-            GlobalRequestResult finalResult = new GlobalRequestResult();
-            for (ClientModel client : realm.getClients()) {
-                GlobalRequestResult currentResult = pushRevocationPolicy(requestUri, realm, client, realm.getNotBefore(), executor);
-                finalResult.addAll(currentResult);
-            }
-            return finalResult;
-        } finally {
-            executor.getHttpClient().getConnectionManager().shutdown();
+        GlobalRequestResult finalResult = new GlobalRequestResult();
+        for (ClientModel client : realm.getClients()) {
+            GlobalRequestResult currentResult = pushRevocationPolicy(requestUri, realm, client, realm.getNotBefore());
+            finalResult.addAll(currentResult);
         }
+        return finalResult;
     }
 
     public GlobalRequestResult pushClientRevocationPolicy(URI requestUri, RealmModel realm, ClientModel client) {
-        ApacheHttpClient4Executor executor = createExecutor();
-
-        try {
-            return pushRevocationPolicy(requestUri, realm, client, client.getNotBefore(), executor);
-        } finally {
-            executor.getHttpClient().getConnectionManager().shutdown();
-        }
+        return pushRevocationPolicy(requestUri, realm, client, client.getNotBefore());
     }
 
 
-    protected GlobalRequestResult pushRevocationPolicy(URI requestUri, RealmModel realm, ClientModel resource, int notBefore, ApacheHttpClient4Executor executor) {
+    protected GlobalRequestResult pushRevocationPolicy(URI requestUri, RealmModel realm, ClientModel resource, int notBefore) {
         List<String> mgmtUrls = getAllManagementUrls(requestUri, resource);
         if (mgmtUrls.isEmpty()) {
             logger.debugf("No management URL or no registered cluster nodes for the client %s", resource.getClientId());
@@ -315,7 +269,7 @@ public class ResourceAdminManager {
         // Propagate this to all hosts
         GlobalRequestResult result = new GlobalRequestResult();
         for (String mgmtUrl : mgmtUrls) {
-            if (sendPushRevocationPolicyRequest(realm, resource, notBefore, executor, mgmtUrl)) {
+            if (sendPushRevocationPolicyRequest(realm, resource, notBefore, mgmtUrl)) {
                 result.addSuccessRequest(mgmtUrl);
             } else {
                 result.addFailedRequest(mgmtUrl);
@@ -324,24 +278,19 @@ public class ResourceAdminManager {
         return result;
     }
 
-    protected boolean sendPushRevocationPolicyRequest(RealmModel realm, ClientModel resource, int notBefore, ApacheHttpClient4Executor client, String managementUrl) {
+    protected boolean sendPushRevocationPolicyRequest(RealmModel realm, ClientModel resource, int notBefore, String managementUrl) {
         PushNotBeforeAction adminAction = new PushNotBeforeAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), notBefore);
         String token = new TokenManager().encodeToken(realm, adminAction);
         logger.infov("pushRevocation resource: {0} url: {1}", resource.getClientId(), managementUrl);
-        ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_PUSH_NOT_BEFORE).build().toString());
-        ClientResponse response;
-        try {
-            response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post();
-        } catch (Exception e) {
-            logger.warn("Failed to send revocation request", e);
-            return false;
-        }
+        URI target = UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_PUSH_NOT_BEFORE).build();
         try {
-            boolean success = response.getStatus() == 204 || response.getStatus() == 200;
+            int status = session.getProvider(HttpClientProvider.class).postText(target.toString(), token);
+            boolean success = status == 204 || status == 200;
             logger.debugf("pushRevocation success for %s: %s", managementUrl, success);
             return success;
-        } finally {
-            response.releaseConnection();
+        } catch (IOException e) {
+            logger.warn("Failed to send revocation request", e);
+            return false;
         }
     }
 
@@ -352,45 +301,35 @@ public class ResourceAdminManager {
             return new GlobalRequestResult();
         }
 
-        ApacheHttpClient4Executor executor = createExecutor();
 
-        try {
-            if (logger.isDebugEnabled()) logger.debug("Sending test nodes availability: " + mgmtUrls);
-
-            // Propagate this to all hosts
-            GlobalRequestResult result = new GlobalRequestResult();
-            for (String mgmtUrl : mgmtUrls) {
-                if (sendTestNodeAvailabilityRequest(realm, client, executor, mgmtUrl)) {
-                    result.addSuccessRequest(mgmtUrl);
-                } else {
-                    result.addFailedRequest(mgmtUrl);
-                }
+        if (logger.isDebugEnabled()) logger.debug("Sending test nodes availability: " + mgmtUrls);
+
+        // Propagate this to all hosts
+        GlobalRequestResult result = new GlobalRequestResult();
+        for (String mgmtUrl : mgmtUrls) {
+            if (sendTestNodeAvailabilityRequest(realm, client, mgmtUrl)) {
+                result.addSuccessRequest(mgmtUrl);
+            } else {
+                result.addFailedRequest(mgmtUrl);
             }
-            return result;
-        } finally {
-            executor.getHttpClient().getConnectionManager().shutdown();
         }
+        return result;
     }
 
-    protected boolean sendTestNodeAvailabilityRequest(RealmModel realm, ClientModel client, ApacheHttpClient4Executor httpClient, String managementUrl) {
+    protected boolean sendTestNodeAvailabilityRequest(RealmModel realm, ClientModel client, String managementUrl) {
         TestAvailabilityAction adminAction = new TestAvailabilityAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, client.getClientId());
         String token = new TokenManager().encodeToken(realm, adminAction);
         logger.debugv("testNodes availability resource: {0} url: {1}", client.getClientId(), managementUrl);
-        ClientRequest request = httpClient.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_TEST_AVAILABLE).build().toString());
-        ClientResponse response;
-        try {
-            response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post();
-        } catch (Exception e) {
-            logger.warn("Availability test failed for uri '" + managementUrl + "'", e);
-            return false;
-        }
+        URI target = UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_TEST_AVAILABLE).build();
         try {
-            boolean success = response.getStatus() == 204 || response.getStatus() == 200;
+            int status = session.getProvider(HttpClientProvider.class).postText(target.toString(), token);
+            boolean success = status == 204 || status == 200;
             logger.debugf("testAvailability success for %s: %s", managementUrl, success);
             return success;
-        } finally {
-            response.releaseConnection();
+        } catch (IOException e) {
+            logger.warn("Availability test failed for uri '" + managementUrl + "'", e);
+            return false;
         }
-    }
+   }
 
 }
diff --git a/services/src/main/java/org/keycloak/services/messages/Messages.java b/services/src/main/java/org/keycloak/services/messages/Messages.java
index f142e9a..8aaa06e 100755
--- a/services/src/main/java/org/keycloak/services/messages/Messages.java
+++ b/services/src/main/java/org/keycloak/services/messages/Messages.java
@@ -173,4 +173,6 @@ public class Messages {
     public static final String INVALID_PARAMETER = "invalidParameterMessage";
 
     public static final String IDENTITY_PROVIDER_LOGIN_FAILURE = "identityProviderLoginFailure";
+
+    public static final String FAILED_LOGOUT = "failedLogout";
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
index 98eb743..f769101 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
@@ -289,7 +289,7 @@ public class ClientResource {
     @POST
     public GlobalRequestResult pushRevocation() {
         auth.requireManage();
-        return new ResourceAdminManager().pushClientRevocationPolicy(uriInfo.getRequestUri(), realm, client);
+        return new ResourceAdminManager(session).pushClientRevocationPolicy(uriInfo.getRequestUri(), realm, client);
     }
 
     /**
@@ -341,7 +341,7 @@ public class ClientResource {
     @POST
     public GlobalRequestResult logoutAll() {
         auth.requireManage();
-        return new ResourceAdminManager().logoutClient(uriInfo.getRequestUri(), realm, client);
+        return new ResourceAdminManager(session).logoutClient(uriInfo.getRequestUri(), realm, client);
     }
 
     /**
@@ -356,7 +356,7 @@ public class ClientResource {
         if (user == null) {
             throw new NotFoundException("User not found");
         }
-        new ResourceAdminManager().logoutUserFromClient(uriInfo.getRequestUri(), realm, client, user, session);
+        new ResourceAdminManager(session).logoutUserFromClient(uriInfo.getRequestUri(), realm, client, user);
     }
 
     /**
@@ -410,7 +410,7 @@ public class ClientResource {
         auth.requireManage();
         logger.debug("Test availability of cluster nodes");
 
-        return new ResourceAdminManager().testNodesAvailability(uriInfo.getRequestUri(), realm, client);
+        return new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client);
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
index 34cdc78..ec33725 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
@@ -1,13 +1,13 @@
 package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
 import org.jboss.resteasy.plugins.providers.multipart.InputPart;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.broker.provider.IdentityProviderFactory;
+import org.keycloak.connections.httpclient.HttpClientProvider;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
@@ -16,7 +16,6 @@ import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.provider.ProviderFactory;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.social.SocialIdentityProvider;
 
@@ -93,16 +92,18 @@ public class IdentityProvidersResource {
 
         String providerId = data.get("providerId").toString();
         String from = data.get("fromUrl").toString();
-        ApacheHttpClient4Executor executor = ResourceAdminManager.createExecutor();
-        InputStream inputStream = null;
+        InputStream inputStream = session.getProvider(HttpClientProvider.class).get(from);
         try {
-            inputStream = executor.createRequest(from).getTarget(InputStream.class);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+            IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
+            Map<String, String> config;
+            config = providerFactory.parseConfig(inputStream);
+            return config;
+        } finally {
+            try {
+                inputStream.close();
+            } catch (IOException e) {
+            }
         }
-        IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
-        Map<String, String> config = providerFactory.parseConfig(inputStream);
-        return config;
     }
 
     @GET
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 129ee5e..b0d171b 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -254,7 +254,7 @@ public class RealmAdminResource {
     @POST
     public GlobalRequestResult pushRevocation() {
         auth.requireManage();
-        return new ResourceAdminManager().pushRealmRevocationPolicy(uriInfo.getRequestUri(), realm);
+        return new ResourceAdminManager(session).pushRealmRevocationPolicy(uriInfo.getRequestUri(), realm);
     }
 
     /**
@@ -266,7 +266,7 @@ public class RealmAdminResource {
     @POST
     public GlobalRequestResult logoutAll() {
         session.sessions().removeUserSessions(realm);
-        return new ResourceAdminManager().logoutAll(uriInfo.getRequestUri(), realm);
+        return new ResourceAdminManager(session).logoutAll(uriInfo.getRequestUri(), realm);
     }
 
     /**
@@ -364,7 +364,6 @@ public class RealmAdminResource {
      * Query events.  Returns all events, or will query based on URL query parameters listed here
      *
      * @param client app or oauth client name
-     * @param types type type
      * @param user user id
      * @param ipAddress
      * @param firstResult
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
index 5c21db1..694b5a9 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
@@ -359,7 +359,7 @@ public class AdapterTestStrategy extends ExternalResource {
         realm = session.realms().getRealmByName("demo");
         // need to cleanup so other tests don't fail, so invalidate http sessions on remote clients.
         UserModel user = session.users().getUserByUsername("bburke@redhat.com", realm);
-        new ResourceAdminManager().logoutUser(null, realm, user, session);
+        new ResourceAdminManager(session).logoutUser(null, realm, user, session);
         realm.setSsoSessionIdleTimeout(originalIdle);
         session.getTransaction().commit();
         session.close();
diff --git a/testsuite/integration/src/test/resources/META-INF/keycloak-server.json b/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
index e2ebf54..a3f508a 100755
--- a/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
+++ b/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
@@ -67,6 +67,13 @@
         "interval": 900
     },
 
+    "connectionsHttpClient": {
+        "default": {
+            "disable-trust-manager": true
+        }
+    },
+
+
     "connectionsJpa": {
         "default": {
             "url": "${keycloak.connectionsJpa.url:jdbc:h2:mem:test}",