keycloak-aplcache

Changes

pom.xml 4(+2 -2)

Details

diff --git a/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java b/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
index e011e11..d5bfdcb 100755
--- a/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
+++ b/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
@@ -1,18 +1,5 @@
 package org.keycloak.connections.jpa;
 
-import org.hibernate.ejb.AvailableSettings;
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
-import org.keycloak.connections.jpa.util.JpaUtils;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-
-import javax.naming.InitialContext;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.Persistence;
-import javax.sql.DataSource;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.DriverManager;
@@ -22,10 +9,25 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
+import javax.naming.InitialContext;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.sql.DataSource;
+
+import org.hibernate.ejb.AvailableSettings;
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
+import org.keycloak.connections.jpa.util.JpaUtils;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ServerInfoAwareProviderFactory;
+
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory {
+public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory, ServerInfoAwareProviderFactory {
 
     private static final Logger logger = Logger.getLogger(DefaultJpaConnectionProviderFactory.class);
 
diff --git a/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java b/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java
index 288e403..2fc645d 100644
--- a/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java
+++ b/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java
@@ -1,10 +1,10 @@
 package org.keycloak.connections.jpa;
 
-import org.keycloak.provider.ServerInfoAwareProviderFactory;
+import org.keycloak.provider.ProviderFactory;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public interface JpaConnectionProviderFactory extends ServerInfoAwareProviderFactory<JpaConnectionProvider> {
+public interface JpaConnectionProviderFactory extends ProviderFactory<JpaConnectionProvider> {
 
 }
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
index 00f3386..ae9701b 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
@@ -1,11 +1,12 @@
 package org.keycloak.connections.mongo;
 
-import com.mongodb.DB;
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoClientURI;
-import com.mongodb.MongoCredential;
-import com.mongodb.ServerAddress;
+import java.lang.reflect.Method;
+import java.net.UnknownHostException;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.net.ssl.SSLSocketFactory;
 
 import org.jboss.logging.Logger;
 import org.keycloak.Config;
@@ -15,18 +16,19 @@ import org.keycloak.connections.mongo.impl.context.TransactionMongoStoreInvocati
 import org.keycloak.connections.mongo.updater.MongoUpdaterProvider;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ServerInfoAwareProviderFactory;
 
-import javax.net.ssl.SSLSocketFactory;
-import java.lang.reflect.Method;
-import java.net.UnknownHostException;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoClientURI;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory {
+public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory, ServerInfoAwareProviderFactory {
 
     // TODO Make it dynamic
     private String[] entities = new String[]{
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java
index bce5fe4..e787ce6 100644
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java
@@ -1,9 +1,9 @@
 package org.keycloak.connections.mongo;
 
-import org.keycloak.provider.ServerInfoAwareProviderFactory;
+import org.keycloak.provider.ProviderFactory;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public interface MongoConnectionProviderFactory extends ServerInfoAwareProviderFactory<MongoConnectionProvider> {
+public interface MongoConnectionProviderFactory extends ProviderFactory<MongoConnectionProvider> {
 }
diff --git a/docbook/auth-server-docs/pom.xml b/docbook/auth-server-docs/pom.xml
index a7c2ddd..546b18d 100755
--- a/docbook/auth-server-docs/pom.xml
+++ b/docbook/auth-server-docs/pom.xml
@@ -114,6 +114,10 @@
                             <name>picketlink.version</name>
                             <value>${picketlink.version}</value>
                         </injection>
+                        <injection>
+                            <name>wildfly.version</name>
+                            <value>${wildfly.version}</value>
+                        </injection>
                     </injections>
                     <options>
                         <xmlTransformerType>saxon</xmlTransformerType>
diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml b/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml
index eda5aca..71c2919 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml
@@ -16,7 +16,7 @@
         </para>
         <para>
             For example to implement the Event Listener SPI you start by implementing EventListenerProviderFactory:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
 package org.acme.provider;
 
 import ...
@@ -43,7 +43,7 @@ public class MyEventListenerProviderFactory implements EventListenerProviderFact
     }
 
 }
-}]]></programlisting>
+]]></programlisting>
             The example uses an imagined MaxList which has a maximum size and is concurrency safe. When the maximum size is reached
             and new entries are added the oldest entry is removed. Keycloak creates a single instance of
             EventListenerProviderFactory which makes it possible to store state for multiple requests. EventListenerProvider
@@ -51,7 +51,7 @@ public class MyEventListenerProviderFactory implements EventListenerProviderFact
         </para>
         <para>
             Next you would implement EventListenerProvider:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
 package org.acme.provider;
 
 import ...
@@ -75,13 +75,61 @@ public class MyEventListenerProvider implements EventListenerProvider {
     }
 
 }
-}]]></programlisting>
+]]></programlisting>
         </para>
         <para>
             The file <literal>META-INF/services/org.keycloak.events.EventListenerProviderFactory</literal> should
             contain the full name of your ProviderFactory implementation:
 <programlisting><![CDATA[org.acme.provider.MyEventListenerProviderFactory]]></programlisting>
         </para>
+        
+        <section>
+            <title>Show info from you SPI implementation in Keycloak admin console</title>
+            <para>
+                Sometimes it is useful to show additional info about your Provider to a Keycloak administrator.
+                You can show provider build time informations (eg. version of custom provider currently installed), 
+                current configuration of the provider (eg. url of remote system your provider talks to) or some operational 
+                info (average time of response from remote system your provider talks to). 
+                Keycloak admin console provides Server Info page to show this kind of information.
+             </para>
+             <para>   
+                To show info from your provider it is enough to implement 
+                <literal>org.keycloak.provider.ServerInfoAwareProviderFactory</literal> interface in your ProviderFactory. 
+                Example implementation for MyEventListenerProviderFactory from previous example:
+                <programlisting><![CDATA[
+package org.acme.provider;
+
+import ...
+
+public class MyEventListenerProviderFactory implements EventListenerProviderFactory, ServerInfoAwareProviderFactory {
+
+    private List<Event> events;
+    private int max;
+     
+...
+
+    @Override
+    public void init(Config.Scope config) {
+        max = config.getInt("max");
+        events = new MaxList(max);
+    }
+
+...
+
+    @Override
+    public Map<String, String> getOperationalInfo() {
+        Map<String, String> ret = new LinkedHashMap<>();
+        ret.put("version", "1.0");
+        ret.put("listSizeMax", max + "");
+        ret.put("listSizeCurrent", events.size() + "");
+        return ret;
+    }
+
+}
+]]></programlisting>
+            
+            </para>
+        </section>    
     </section>
 
     <section>
@@ -98,13 +146,13 @@ public class MyEventListenerProvider implements EventListenerProvider {
                 To register a provider using Modules first create a module. To do this you can either use the jboss-cli
                 script or manually create a folder inside KEYCLOAK_HOME/modules and add your jar and a <literal>module.xml</literal>.
                 For example to add the event listener sysout example provider using the jboss-cli script execute:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
     KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.event-sysout --resources=target/event-listener-sysout-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-model-api,org.keycloak.keycloak-events-api"
-}]]></programlisting>
+]]></programlisting>
                 Or to manually create it start by creating the folder <literal>KEYCLOAK_HOME/modules/org/keycloak/examples/event-sysout/main</literal>.
                 Then copy <literal>event-listener-sysout-example.jar</literal> to this folder and create <literal>module.xml</literal>
                 with the following content:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
 <?xml version="1.0" encoding="UTF-8"?>
 <module xmlns="urn:jboss:module:1.1" name="org.keycloak.examples.event-sysout">
     <resources>
@@ -116,7 +164,7 @@ public class MyEventListenerProvider implements EventListenerProvider {
         <module name="org.keycloak.keycloak-events-api"/>
     </dependencies>
 </module>
-}]]></programlisting>
+]]></programlisting>
             </para>
             <para>
                 Once you've created the module you need to register this module with Keycloak. This is done by editing
diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml b/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml
index 558f943..549bc84 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml
@@ -43,9 +43,9 @@
 
 
         <section id="overlay_install">
-            <title>Install on existing WildFly 9.0.1.Final</title>
+            <title>Install on existing WildFly &wildfly.version;</title>
             <para>
-                Keycloak can be installed into an existing WildFly 9.0.0.Final server. To do this download
+                Keycloak can be installed into an existing WildFly &wildfly.version; server. To do this download
                 <literal>keycloak-overlay-&project.version;.zip</literal> or <literal>keycloak-overlay-&project.version;.tar.gz</literal>.
                 Once downloaded extract into the root directory of your WildFly installation. To start WildFly with Keycloak
                 run:
@@ -62,11 +62,15 @@
             <para>
                 To add Keycloak to other sever configurations (standalone.xml, standalone-ha.xml, etc.) start the server with
                 the desired server-config. If you are running the server in standalone mode run:
-                <programlisting>cd &lt;WILDFLY_HOME&gt;/bin
-                    ./jboss-cli.sh -c --file=keycloak-install.cli</programlisting>
+<programlisting>
+cd &lt;WILDFLY_HOME&gt;/bin
+./jboss-cli.sh -c --file=keycloak-install.cli
+</programlisting>
                 Or if you are running in clustering (HA) mode (by having used -c standalone-ha.xml) then run:
-                <programlisting>cd &lt;WILDFLY_HOME&gt;/bin
-                    ./jboss-cli.sh -c --file=keycloak-install-ha.cli</programlisting>
+<programlisting>
+cd &lt;WILDFLY_HOME&gt;/bin
+./jboss-cli.sh -c --file=keycloak-install-ha.cli
+</programlisting>
                 You may see exceptions in the server log, but after restarting the server they should be gone.
                 You can restart the server with:
                 <programlisting>&lt;WILDFLY_HOME&gt;/bin/jboss-cli.sh -c :reload</programlisting>
@@ -75,7 +79,7 @@
         <section>
             <title>Install on existing JBoss EAP 6.4.0.GA</title>
             <para>
-                Same procedure as WildFly 9.0.1.Final, but download <literal>keycloak-overlay-eap6-&project.version;.zip</literal> or <literal>keycloak-overlay-eap6-&project.version;.tar.gz</literal>.
+                Same procedure as WildFly &wildfly.version;, but download <literal>keycloak-overlay-eap6-&project.version;.zip</literal> or <literal>keycloak-overlay-eap6-&project.version;.tar.gz</literal>.
             </para>
         </section>
         <section>
@@ -85,7 +89,7 @@
                 To install it first download <literal>keycloak-demo-&project.version;.zip</literal> or
                 <literal>keycloak-demo-&project.version;.tar.gz</literal>. Once downloaded extract it inside
                 <literal>keycloak-demo-&project.version;</literal> you'll find <literal>keycloak</literal> which contains
-                a full WildFly 9.0.0.Final server with Keycloak Server and Adapters included. You'll also find <literal>docs</literal>
+                a full WildFly &wildfly.version; server with Keycloak Server and Adapters included. You'll also find <literal>docs</literal>
                 and <literal>examples</literal> which contains everything you need to get started developing applications that use Keycloak.
             </para>
             <para>
@@ -437,12 +441,12 @@ All configuration options are optional. Default value for directory is <literal>
                 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><![CDATA[
+"connectionsHttpClient": {
+    "default": {
+        "disable-trust-manager": true
+    }
+},
 ]]></programlisting>
                 Possible configuration options are:
                 <variablelist>
@@ -659,25 +663,25 @@ All configuration options are optional. Default value for directory is <literal>
                             to do with the <literal>keytool</literal> utility that comes with the Java jdk.
                         </para>
                         <para>
-    <programlisting>
-    $ keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
-        Enter keystore password: secret
-        Re-enter new password: secret
-        What is your first and last name?
-        [Unknown]:  localhost
-        What is the name of your organizational unit?
-        [Unknown]:  Keycloak
-        What is the name of your organization?
-        [Unknown]:  Red Hat
-        What is the name of your City or Locality?
-        [Unknown]:  Westford
-        What is the name of your State or Province?
-        [Unknown]:  MA
-        What is the two-letter country code for this unit?
-        [Unknown]:  US
-        Is CN=localhost, OU=Keycloak, O=Test, L=Westford, ST=MA, C=US correct?
-        [no]:  yes
-    </programlisting>
+<programlisting>
+$ keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
+    Enter keystore password: secret
+    Re-enter new password: secret
+    What is your first and last name?
+    [Unknown]:  localhost
+    What is the name of your organizational unit?
+    [Unknown]:  Keycloak
+    What is the name of your organization?
+    [Unknown]:  Red Hat
+    What is the name of your City or Locality?
+    [Unknown]:  Westford
+    What is the name of your State or Province?
+    [Unknown]:  MA
+    What is the two-letter country code for this unit?
+    [Unknown]:  US
+    Is CN=localhost, OU=Keycloak, O=Test, L=Westford, ST=MA, C=US correct?
+    [no]:  yes
+</programlisting>
                         </para>
                         <para>
                             You should answer <literal>What is your first and last name ?</literal> question with
@@ -693,44 +697,44 @@ All configuration options are optional. Default value for directory is <literal>
                         </para>
                         <para>
                             The first thing to do is generate a Certificate Request:
-    <programlisting>
-    $ keytool -certreq -alias yourdomain -keystore keycloak.jks > keycloak.careq
-    </programlisting>
+<programlisting>
+$ keytool -certreq -alias yourdomain -keystore keycloak.jks > keycloak.careq
+</programlisting>
                         </para>
                         <para>
                              Where <literal>yourdomain</literal> is a DNS name for which this certificate is generated for.
                              Keytool generates the request:
-    <programlisting>
-    -----BEGIN NEW CERTIFICATE REQUEST-----
-    MIIC2jCCAcICAQAwZTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMREwDwYDVQQHEwhXZXN0Zm9y
-    ZDEQMA4GA1UEChMHUmVkIEhhdDEQMA4GA1UECxMHUmVkIEhhdDESMBAGA1UEAxMJbG9jYWxob3N0
-    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7kck2TaavlEOGbcpi9c0rncY4HhdzmY
-    Ax2nZfq1eZEaIPqI5aTxwQZzzLDK9qbeAd8Ji79HzSqnRDxNYaZu7mAYhFKHgixsolE3o5Yfzbw1
-    29Rvy+eUVe+WZxv5oo9wolVVpdSINIMEL2LaFhtX/c1dqiqYVpfnvFshZQaIg2nL8juzZcBjj4as
-    H98gIS7khql/dkZKsw9NLvyxgJvp7PaXurX29fNf3ihG+oFrL22oFyV54BWWxXCKU/GPn61EGZGw
-    Ft2qSIGLdctpMD1aJR2bcnlhEjZKDksjQZoQ5YMXaAGkcYkG6QkgrocDE2YXDbi7GIdf9MegVJ35
-    2DQMpwIDAQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQUQwlZJBA+fjiDdiVzaO9vrE/i
-    n2swDQYJKoZIhvcNAQELBQADggEBAC5FRvMkhal3q86tHPBYWBuTtmcSjs4qUm6V6f63frhveWHf
-    PzRrI1xH272XUIeBk0gtzWo0nNZnf0mMCtUBbHhhDcG82xolikfqibZijoQZCiGiedVjHJFtniDQ
-    9bMDUOXEMQ7gHZg5q6mJfNG9MbMpQaUVEEFvfGEQQxbiFK7hRWU8S23/d80e8nExgQxdJWJ6vd0X
-    MzzFK6j4Dj55bJVuM7GFmfdNC52pNOD5vYe47Aqh8oajHX9XTycVtPXl45rrWAH33ftbrS8SrZ2S
-    vqIFQeuLL3BaHwpl3t7j2lMWcK1p80laAxEASib/fAwrRHpLHBXRcq6uALUOZl4Alt8=
-    -----END NEW CERTIFICATE REQUEST-----
-     </programlisting>
+<programlisting>
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIIC2jCCAcICAQAwZTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMREwDwYDVQQHEwhXZXN0Zm9y
+ZDEQMA4GA1UEChMHUmVkIEhhdDEQMA4GA1UECxMHUmVkIEhhdDESMBAGA1UEAxMJbG9jYWxob3N0
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7kck2TaavlEOGbcpi9c0rncY4HhdzmY
+Ax2nZfq1eZEaIPqI5aTxwQZzzLDK9qbeAd8Ji79HzSqnRDxNYaZu7mAYhFKHgixsolE3o5Yfzbw1
+29Rvy+eUVe+WZxv5oo9wolVVpdSINIMEL2LaFhtX/c1dqiqYVpfnvFshZQaIg2nL8juzZcBjj4as
+H98gIS7khql/dkZKsw9NLvyxgJvp7PaXurX29fNf3ihG+oFrL22oFyV54BWWxXCKU/GPn61EGZGw
+Ft2qSIGLdctpMD1aJR2bcnlhEjZKDksjQZoQ5YMXaAGkcYkG6QkgrocDE2YXDbi7GIdf9MegVJ35
+2DQMpwIDAQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQUQwlZJBA+fjiDdiVzaO9vrE/i
+n2swDQYJKoZIhvcNAQELBQADggEBAC5FRvMkhal3q86tHPBYWBuTtmcSjs4qUm6V6f63frhveWHf
+PzRrI1xH272XUIeBk0gtzWo0nNZnf0mMCtUBbHhhDcG82xolikfqibZijoQZCiGiedVjHJFtniDQ
+9bMDUOXEMQ7gHZg5q6mJfNG9MbMpQaUVEEFvfGEQQxbiFK7hRWU8S23/d80e8nExgQxdJWJ6vd0X
+MzzFK6j4Dj55bJVuM7GFmfdNC52pNOD5vYe47Aqh8oajHX9XTycVtPXl45rrWAH33ftbrS8SrZ2S
+vqIFQeuLL3BaHwpl3t7j2lMWcK1p80laAxEASib/fAwrRHpLHBXRcq6uALUOZl4Alt8=
+-----END NEW CERTIFICATE REQUEST-----
+</programlisting>
                         </para>
                         <para>
                             Send this ca request to your CA.  The CA will issue you a signed certificate and send it to you.
                             Before you import your new cert, you must obtain and import the root certificate of the CA.
                             You can download the cert from CA (ie.: root.crt) and import as follows:
-    <programlisting>
-    $ keytool -import -keystore keycloak.jks -file root.crt -alias root
-    </programlisting>
+<programlisting>
+$ keytool -import -keystore keycloak.jks -file root.crt -alias root
+</programlisting>
                         </para>
                         <para>
                             Last step is import your new CA generated certificate to your keystore:
-    <programlisting>
-    $ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificate.cer
-    </programlisting>
+<programlisting>
+$ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificate.cer
+</programlisting>
                         </para>
                     </section>
                 </section>
@@ -744,18 +748,19 @@ All configuration options are optional. Default value for directory is <literal>
                     </para>
                     <para>
                         To the <literal>security-realms</literal> element add:
-                        <programlisting><![CDATA[<security-realm name="UndertowRealm">
-        <server-identities>
-            <ssl>
-                <keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="secret" />
-            </ssl>
-        </server-identities>
-    </security-realm>]]></programlisting>
+<programlisting><![CDATA[
+<security-realm name="UndertowRealm">
+    <server-identities>
+        <ssl>
+            <keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="secret" />
+        </ssl>
+    </server-identities>
+</security-realm>
+]]></programlisting>
                     </para>
                     <para>
                         Find the element <literal>&lt;server name="default-server"&gt;</literal> (it's a child element of <literal>&lt;subsystem xmlns="urn:jboss:domain:undertow:1.0"&gt;</literal>) and add:
-                        <programlisting><![CDATA[<https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/>
-    ]]></programlisting>
+                        <programlisting><![CDATA[<https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/>]]></programlisting>
                     </para>
                     <para>
                         Check the <ulink url="https://docs.jboss.org/author/display/WFLY8/Undertow+(web)+subsystem+configuration">Wildfly Undertow</ulink> documentation for more information on fine tuning the socket connections.
@@ -865,12 +870,12 @@ All configuration options are optional. Default value for directory is <literal>
         </para>
         <para>
             To do this, add the <literal>default-web-module</literal> attribute in the Undertow subystem in standalone.xml.
-            <programlisting><![CDATA[
+<programlisting><![CDATA[
 <subsystem xmlns="urn:jboss:domain:undertow:2.0">
-            <server name="default-server">
-                <host name="default-host" alias="localhost" default-web-module="keycloak-server.war">
-                    <location name="/" handler="welcome-content"/>
-                </host>
+    <server name="default-server">
+        <host name="default-host" alias="localhost" default-web-module="keycloak-server.war">
+            <location name="/" handler="welcome-content"/>
+        </host>
 ]]></programlisting>
         </para>
         <para>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index e35e1c6..c5f6316 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -877,7 +877,7 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, $route, se
     $scope.viewImportDetails = function() {
         $modal.open({
             templateUrl: resourceUrl + '/partials/modal/view-object.html',
-            controller: 'JsonModalCtrl',
+            controller: 'ObjectModalCtrl',
             resolve: {
                 object: function () {
                     return $scope.client;
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html
index 4237f7d..04c2339 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html
@@ -37,7 +37,7 @@
             <td>{{mapper.name}}</td>
             <td>{{mapperTypes[mapper.protocolMapper].category}}</td>
             <td>{{mapperTypes[mapper.protocolMapper].name}}</td>
-            <td><input type="checkbox" ng-model="mapper.isChecked"></td>
+            <td><input type="checkbox" ng-model="mapper.isChecked" id="{{mapper.protocolMapper}}"></td>
         </tr>
         <tr data-ng-show="mappers.length == 0">
             <td>{{:: 'no-mappers-available' | translate}}</td>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/otp-policy.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/otp-policy.html
index bf06303..1f8890e 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/otp-policy.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/otp-policy.html
@@ -54,7 +54,7 @@
         <div class="form-group" data-ng-show="realm.otpPolicyType == 'hotp'">
             <label class="col-md-2 control-label" for="counter">Initial Counter</label>
             <div class="col-md-6">
-                <input class="form-control" type="text" id="counter" name="counter" data-ng-model="realm.otpPolicyInitialCounter" autofocus>
+                <input class="form-control" type="number" required min="1" max="120" id="counter" name="counter" data-ng-model="realm.otpPolicyInitialCounter" autofocus>
             </div>
             <kc-tooltip>What should the initial counter value be?</kc-tooltip>
         </div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html
index 0161a30..8a81237 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html
@@ -20,8 +20,8 @@
         <tbody>
         <tr ng-repeat="requiredAction in requiredActions" data-ng-show="requiredActions.length > 0">
             <td>{{requiredAction.name}}</td>
-            <td><input type="checkbox" ng-model="requiredAction.enabled" ng-change="updateRequiredAction(requiredAction)"></td>
-            <td><input type="checkbox" ng-model="requiredAction.defaultAction" ng-change="updateRequiredAction(requiredAction)"></td>
+            <td><input type="checkbox" ng-model="requiredAction.enabled" ng-change="updateRequiredAction(requiredAction)" id="{{requiredAction.alias}}.enabled"></td>
+            <td><input type="checkbox" ng-model="requiredAction.defaultAction" ng-change="updateRequiredAction(requiredAction)" id="{{requiredAction.alias}}.defaultAction"></td>
         </tr>
         <tr data-ng-show="requiredActions.length == 0">
             <td>No required actions configured</td>
diff --git a/integration/jetty/jetty-adapter-spi/pom.xml b/integration/jetty/jetty-adapter-spi/pom.xml
index bbe9e88..40839ef 100755
--- a/integration/jetty/jetty-adapter-spi/pom.xml
+++ b/integration/jetty/jetty-adapter-spi/pom.xml
@@ -43,21 +43,21 @@
             <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-server</artifactId>
             <version>${jetty9.version}</version>
-            <scope>compile</scope>
+            <scope>provided</scope>
         </dependency>
 
         <dependency>
             <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-util</artifactId>
             <version>${jetty9.version}</version>
-            <scope>compile</scope>
+            <scope>provided</scope>
         </dependency>
 
         <dependency>
             <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-security</artifactId>
             <version>${jetty9.version}</version>
-            <scope>compile</scope>
+            <scope>provided</scope>
         </dependency>
 
 		<dependency>
diff --git a/integration/js/src/main/resources/keycloak.js b/integration/js/src/main/resources/keycloak.js
index 7b378de..09e0d86 100755
--- a/integration/js/src/main/resources/keycloak.js
+++ b/integration/js/src/main/resources/keycloak.js
@@ -153,23 +153,23 @@
                 + '&response_type=code';
 
             if (options && options.prompt) {
-                url += '&prompt=' + options.prompt;
+                url += '&prompt=' + encodeURIComponent(options.prompt);
             }
 
             if (options && options.loginHint) {
-                url += '&login_hint=' + options.loginHint;
+                url += '&login_hint=' + encodeURIComponent(options.loginHint);
             }
 
             if (options && options.idpHint) {
-                url += '&kc_idp_hint=' + options.idpHint;
+                url += '&kc_idp_hint=' + encodeURIComponent(options.idpHint);
             }
 
             if (options && options.scope) {
-                url += '&scope=' + options.scope;
+                url += '&scope=' + encodeURIComponent(options.scope);
             }
 
             if (options && options.locale) {
-                url += '&ui_locales=' + options.locale;
+                url += '&ui_locales=' + encodeURIComponent(options.locale);
             }
 
             return url;
diff --git a/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java b/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java
index 1aa67f0..3be665b 100644
--- a/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java
+++ b/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java
@@ -1,9 +1,9 @@
 package org.keycloak.adapters.osgi;
 
 import java.net.URL;
+import java.security.SecureRandom;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Random;
 
 import org.eclipse.jetty.security.ConstraintMapping;
 import org.eclipse.jetty.util.security.Constraint;
@@ -133,7 +133,8 @@ public class PaxWebIntegrationService {
         Constraint constraint = constraintMapping.getConstraint();
         String[] roles = constraint.getRoles();
         // name property is unavailable on constraint object :/
-        String name = "Constraint-" + new Random().nextInt();
+
+        String name = "Constraint-" + new SecureRandom().nextInt(Integer.MAX_VALUE);
 
         int dataConstraint = constraint.getDataConstraint();
         String dataConstraintStr;
diff --git a/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java b/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java
index 97d17b1..7674047 100644
--- a/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java
+++ b/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java
@@ -3,15 +3,15 @@ package org.keycloak.provider;
 import java.util.Map;
 
 /**
- * Marker interface for ProviderFactory of Provider which wants to show some info on "Server Info" page in Admin console.
+ * Marker interface for {@link ProviderFactory} of Provider which wants to show some info on "Server Info" page in Admin console.
  * 
  * @author Vlastimil Elias (velias at redhat dot com)
  */
-public interface ServerInfoAwareProviderFactory<T extends Provider> extends ProviderFactory<T> {
+public interface ServerInfoAwareProviderFactory {
 
     /**
-     * Get operational info about given provider. This info contains informations about providers configuration and operational conditions (eg. errors in connection to remote systems etc) which is
-     * shown on "Server Info" page.
+     * Return actual info about the provider. This info contains informations about providers configuration and operational conditions (eg. errors in connection to remote systems etc) which is
+     * shown on "Server Info" page then.
      * 
      * @return Map with keys describing value and relevant values itself
      */

pom.xml 4(+2 -2)

diff --git a/pom.xml b/pom.xml
index 12a346e..85409fe 100755
--- a/pom.xml
+++ b/pom.xml
@@ -48,8 +48,8 @@
         <dom4j.version>1.6.1</dom4j.version>
         <xml-apis.version>1.4.01</xml-apis.version>
         <slf4j.version>1.7.7</slf4j.version>
-        <wildfly.version>9.0.1.Final</wildfly.version>
-        <wildfly.core.version>1.0.1.Final</wildfly.core.version>
+        <wildfly.version>9.0.2.Final</wildfly.version>
+        <wildfly.core.version>1.0.2.Final</wildfly.core.version>
         <wildfly.build-tools.version>1.0.0.Final</wildfly.build-tools.version>
 
         <!-- this is EAP 6.4 alpha, publicly available -->
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
index 4ef2a63..660b1c4 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
@@ -1,5 +1,17 @@
 package org.keycloak.services.resources.admin.info;
 
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.core.Context;
+
 import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.broker.provider.IdentityProviderFactory;
 import org.keycloak.events.EventType;
@@ -21,10 +33,6 @@ import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
 import org.keycloak.social.SocialIdentityProvider;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.core.Context;
-import java.util.*;
-
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
@@ -73,7 +81,6 @@ public class ServerInfoAdminResource {
         for (Spi spi : spis) {
             SpiInfoRepresentation spiRep = new SpiInfoRepresentation();
             spiRep.setInternal(spi.isInternal());
-            spiRep.setSystemInfo(ServerInfoAwareProviderFactory.class.isAssignableFrom(spi.getProviderFactoryClass()));
 
             List<String> providerIds = new LinkedList<>(session.listProviderIds(spi.getProviderClass()));
             Collections.sort(providerIds);
@@ -83,8 +90,9 @@ public class ServerInfoAdminResource {
             if (providerIds != null) {
                 for (String name : providerIds) {
                     ProviderRepresentation provider = new ProviderRepresentation();
-                    if (spiRep.isSystemInfo()) {
-                        provider.setOperationalInfo(((ServerInfoAwareProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(spi.getProviderClass(), name)).getOperationalInfo());
+                    ProviderFactory<?> pi = session.getKeycloakSessionFactory().getProviderFactory(spi.getProviderClass(), name);
+                    if (ServerInfoAwareProviderFactory.class.isAssignableFrom(pi.getClass())) {
+                        provider.setOperationalInfo(((ServerInfoAwareProviderFactory) pi).getOperationalInfo());
                     }
                     providers.put(name, provider);
                 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java b/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java
index 3f94a5a..1277f8c 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java
@@ -8,7 +8,6 @@ import java.util.Map;
 public class SpiInfoRepresentation {
 
     private boolean internal;
-    private boolean systemInfo;
 
     private Map<String, ProviderRepresentation> providers;
 
@@ -20,14 +19,6 @@ public class SpiInfoRepresentation {
         this.internal = internal;
     }
 
-    public boolean isSystemInfo() {
-        return systemInfo;
-    }
-
-    public void setSystemInfo(boolean systemInfo) {
-        this.systemInfo = systemInfo;
-    }
-
     public Map<String, ProviderRepresentation> getProviders() {
         return providers;
     }
diff --git a/testsuite/integration-arquillian/tests/base/pom.xml b/testsuite/integration-arquillian/tests/base/pom.xml
index 6317df8..5c409ab 100644
--- a/testsuite/integration-arquillian/tests/base/pom.xml
+++ b/testsuite/integration-arquillian/tests/base/pom.xml
@@ -15,7 +15,18 @@
         <exclude.console>-</exclude.console>
         <exclude.account>-</exclude.account>
     </properties>
-
+	<dependencies>
+	    <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-util-embedded-ldap</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>bouncycastle</groupId>
+                    <artifactId>bcprov-jdk15</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+	</dependencies>
     <build>
         <plugins>
             <plugin>
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/AdminConsoleRealm.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/AdminConsoleRealm.java
index 4fd57ba..852133b 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/AdminConsoleRealm.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/AdminConsoleRealm.java
@@ -57,7 +57,7 @@ public class AdminConsoleRealm extends AdminConsoleRealmsRoot {
         private WebElement rolesLink;
         @FindBy(partialLinkText = "Identity Providers")
         private WebElement identityProvidersLink;
-        @FindBy(partialLinkText = "User Feferation")
+        @FindBy(partialLinkText = "User Federation")
         private WebElement userFederationLink;
         @FindBy(partialLinkText = "Authentication")
         private WebElement authenticationLink;
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/Authentication.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/Authentication.java
index 05b0024..858de40 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/Authentication.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/Authentication.java
@@ -3,7 +3,7 @@ package org.keycloak.testsuite.console.page.authentication;
 import org.keycloak.testsuite.console.page.AdminConsoleRealm;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
-import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
+import static org.keycloak.testsuite.util.WaitUtils.*;
 
 /**
  * @author tkyjovsk
@@ -20,6 +20,9 @@ public class Authentication extends AdminConsoleRealm {
     @FindBy(xpath = "//div[contains(@class, 'alert-success')]")
     private WebElement success;
     
+    @FindBy(xpath = "//button[@class='close']/span")
+    private WebElement close;
+    
     public String getSuccessMessage() {
         waitAjaxForElement(success);
         return success.getText();
@@ -30,6 +33,13 @@ public class Authentication extends AdminConsoleRealm {
         return error.getText();
     }
     
+    public void closeNotification() {
+        if (close.isDisplayed()) {
+            close.click();
+        }
+        waitAjaxForElementNotVisible(close);
+    }
+    
     public AuthenticationTabs tabs() {
         return authenticationTabs;
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java
index 0ea6af2..b6f182a 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java
@@ -7,11 +7,17 @@ import org.openqa.selenium.support.FindBy;
 /**
  * @author tkyjovsk
  * @author mhajas
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
  */
 public class RequiredActions extends Authentication {
 
-    public final static String ENABLED = "enabled";
-    public final static String DEFAULT_ACTION = "defaultAction";
+    public final static String ENABLED = ".enabled";
+    public final static String DEFAULT = ".defaultAction";
+    public final static String CONFIGURE_TOTP = "CONFIGURE_TOTP";
+    public final static String UPDATE_PROFILE = "UPDATE_PROFILE";
+    public final static String TERMS_AND_CONDITIONS = "terms_and_conditions";
+    public final static String UPDATE_PASSWORD = "UPDATE_PASSWORD";
+    public final static String VERIFY_EMAIL = "VERIFY_EMAIL";
 
     @FindBy(tagName = "table")
     private WebElement requiredActionTable;
@@ -21,51 +27,59 @@ public class RequiredActions extends Authentication {
         return super.getUriFragment() + "/required-actions";
     }
 
-    private void setRequiredActionValue(String row, String column, boolean value) {
-        WebElement checkbox = requiredActionTable.findElement(By.xpath("//td[text()='" + row + "']/..//input[@ng-model='requiredAction." + column + "']"));
+    private void setRequiredActionValue(String id, boolean value) {
+        WebElement checkbox = requiredActionTable.findElement(By.id(id));
 
         if (checkbox.isSelected() != value) {
             checkbox.click();
         }
     }
 
+    private void setRequiredActionEnabledValue(String id, boolean value) {
+        setRequiredActionValue(id + ENABLED, value);
+    }
+
+    private void setRequiredActionDefaultValue(String id, boolean value) {
+        setRequiredActionValue(id + DEFAULT, value);
+    }
+
     public void setTermsAndConditionEnabled(boolean value) {
-        setRequiredActionValue("Terms and Conditions", ENABLED, value);
+        setRequiredActionEnabledValue(TERMS_AND_CONDITIONS, value);
     }
 
     public void setTermsAndConditionDefaultAction(boolean value) {
-        setRequiredActionValue("Terms and Conditions", DEFAULT_ACTION, value);
+        setRequiredActionDefaultValue(TERMS_AND_CONDITIONS, value);
     }
 
     public void setVerifyEmailEnabled(boolean value) {
-        setRequiredActionValue("Verify Email", ENABLED, value);
+        setRequiredActionEnabledValue(VERIFY_EMAIL, value);
     }
 
     public void setVerifyEmailDefaultAction(boolean value) {
-        setRequiredActionValue("Verify Email", DEFAULT_ACTION, value);
+        setRequiredActionDefaultValue(VERIFY_EMAIL, value);
     }
 
     public void setUpdatePasswordEnabled(boolean value) {
-        setRequiredActionValue("Update Password", ENABLED, value);
+        setRequiredActionEnabledValue(UPDATE_PASSWORD, value);
     }
 
     public void setUpdatePasswordDefaultAction(boolean value) {
-        setRequiredActionValue("Update Password", DEFAULT_ACTION, value);
+        setRequiredActionDefaultValue(UPDATE_PASSWORD, value);
     }
 
     public void setConfigureTotpEnabled(boolean value) {
-        setRequiredActionValue("Configure Totp", ENABLED, value);
+        setRequiredActionEnabledValue(CONFIGURE_TOTP, value);
     }
 
     public void setConfigureTotpDefaultAction(boolean value) {
-        setRequiredActionValue("Configure Totp", DEFAULT_ACTION, value);
+        setRequiredActionDefaultValue(CONFIGURE_TOTP, value);
     }
 
     public void setUpdateProfileEnabled(boolean value) {
-        setRequiredActionValue("Update Profile", ENABLED, value);
+        setRequiredActionEnabledValue(UPDATE_PROFILE, value);
     }
 
     public void setUpdateProfileDefaultAction(boolean value) {
-        setRequiredActionValue("Update Profile", DEFAULT_ACTION, value);
+        setRequiredActionDefaultValue(UPDATE_PROFILE, value);
     }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/ClientMappers.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/ClientMappers.java
index d56dca5..10fb7e5 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/ClientMappers.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/ClientMappers.java
@@ -1,14 +1,112 @@
 package org.keycloak.testsuite.console.page.clients;
 
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.testsuite.console.page.fragment.DataTable;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  *
  * @author tkyjovsk
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
  */
 public class ClientMappers extends Client {
 
+    public static final String ADD_BUILTIN = "Add Builtin";
+
+    @FindBy(tagName = "table")
+    private ClientMapperTable table;
+
     @Override
     public String getUriFragment() {
         return super.getUriFragment() + "/mappers";
     }
 
+    public ClientMapperTable mapperTable() {
+        return table;
+    }
+
+    public class ClientMapperTable extends DataTable {
+
+        public List<ProtocolMapperRepresentation> searchMappings(String searchPattern) {
+            search(searchPattern);
+            return getMappingsFromRows();
+        }
+
+        public void createMapper() {
+            waitAjaxForBody();
+            clickHeaderLink(CREATE);
+        }
+
+        public void addBuiltin() {
+            waitAjaxForBody();
+            clickHeaderLink(ADD_BUILTIN);
+        }
+
+        public void clickMapper(String mapperName) {
+            waitAjaxForBody();
+            body().findElement(By.linkText(mapperName)).click();
+        }
+
+        public void clickMapper(ProtocolMapperRepresentation mapper) {
+            clickMapper(mapper.getName());
+        }
+
+        private void clickMapperActionButton(String mapperName, String buttonText) {
+            waitAjaxForBody();
+            clickRowActionButton(getRowByLinkText(mapperName), buttonText);
+        }
+
+        private void clickMapperActionButton(ProtocolMapperRepresentation mapper, String buttonName) {
+            clickMapperActionButton(mapper.getName(), buttonName);
+        }
+
+        public void editMapper(String mapperName) {
+            clickMapperActionButton(mapperName, EDIT);
+        }
+
+        public void editMapper(ProtocolMapperRepresentation mapper) {
+            clickMapperActionButton(mapper, EDIT);
+        }
+
+        public void deleteMapper(String mapperName) {
+            clickMapperActionButton(mapperName, DELETE);
+        }
+
+        public void deleteMapper(ProtocolMapperRepresentation mapper) {
+            clickMapperActionButton(mapper, DELETE);
+        }
+
+        public ProtocolMapperRepresentation getMappingFromRow(WebElement row) {
+            if (!row.isDisplayed()) {return null;} // Is that necessary?
+
+            ProtocolMapperRepresentation mappingsRepresentation = new ProtocolMapperRepresentation();
+            List<WebElement> cols = row.findElements(By.tagName("td"));
+
+
+            mappingsRepresentation.setName(cols.get(0).getText());
+            //mappingsRepresentation.setProtocol(cols.get(1).getText());
+            mappingsRepresentation.setProtocolMapper(cols.get(2).getText());
+
+            return mappingsRepresentation;
+        }
+
+        public List<ProtocolMapperRepresentation> getMappingsFromRows() {
+            List<ProtocolMapperRepresentation> mappings = new ArrayList<ProtocolMapperRepresentation>();
+
+            for (WebElement row : rows()) {
+                ProtocolMapperRepresentation mapperRepresentation = getMappingFromRow(row);
+                if (mapperRepresentation != null) {
+                    mappings.add(mapperRepresentation);
+                }
+            }
+
+            return mappings;
+        }
+    }
+
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappers.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappers.java
new file mode 100644
index 0000000..962e7a5
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappers.java
@@ -0,0 +1,21 @@
+package org.keycloak.testsuite.console.page.clients;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.testsuite.console.page.AdminConsoleCreate;
+
+/**
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
+ */
+public class CreateClientMappers extends AdminConsoleCreate {
+
+    @Page
+    private CreateClientMappersForm form;
+
+    public CreateClientMappers() {
+        setEntity("mappers");
+    }
+
+    public CreateClientMappersForm form() {
+        return form;
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappersForm.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappersForm.java
new file mode 100644
index 0000000..900b4d2
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappersForm.java
@@ -0,0 +1,187 @@
+package org.keycloak.testsuite.console.page.clients;
+
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
+import org.keycloak.testsuite.page.Form;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.support.FindBy;
+import org.openqa.selenium.support.ui.Select;
+
+import java.util.List;
+
+/**
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
+ *
+ * TODO: SAML
+ */
+public class CreateClientMappersForm extends Form {
+
+    // Mappers types
+    public static final String HARDCODED_ROLE = "Hardcoded Role";
+    public static final String HARDCODED_CLAIM = "Hardcoded claim";
+    public static final String USER_SESSION_NOTE = "User Session Note";
+    public static final String ROLE_NAME_MAPPER = "Role Name Mapper";
+    public static final String USER_ADDRESS = "User Address";
+    public static final String USERS_FULL_NAME = "User's full name";
+    public static final String USER_ATTRIBUTE = "User Attribute";
+    public static final String USER_PROPERTY = "User Property";
+
+    @FindBy(id = "name")
+    private WebElement nameElement;
+
+    @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='consentRequired']]")
+    private OnOffSwitch consentRequiredSwitch;
+
+    @FindBy(id = "consentText")
+    private WebElement consentTextElement;
+
+    @FindBy(id = "mapperTypeCreate")
+    private Select mapperTypeSelect;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Property']//following-sibling::node()//input[@type='text']")
+    private WebElement propertyInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Attribute']//following-sibling::node()//input[@type='text']")
+    private WebElement userAttributeInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Session Note']//following-sibling::node()//input[@type='text']")
+    private WebElement userSessionNoteInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Multivalued']//following-sibling::node()//div[@class='onoffswitch']")
+    private OnOffSwitch multivaluedInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Role']//following-sibling::node()//input[@type='text']")
+    private WebElement roleInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='New Role Name']//following-sibling::node()//input[@type='text']")
+    private WebElement newRoleInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Token Claim Name']//following-sibling::node()//input[@type='text']")
+    private WebElement tokenClaimNameInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim value']//following-sibling::node()//input[@type='text']")
+    private WebElement tokenClaimValueInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim JSON Type']//following-sibling::node()//select")
+    private Select claimJSONTypeInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to ID token']//following-sibling::node()//div[@class='onoffswitch']")
+    private OnOffSwitch addToIDTokenInput;
+
+    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to access token']//following-sibling::node()//div[@class='onoffswitch']")
+    private OnOffSwitch addToAccessTokenInput;
+
+    public boolean isConsentRequired() {
+        return consentRequiredSwitch.isOn();
+    }
+
+    public void setConsentRequired(boolean consentRequired) {
+        consentRequiredSwitch.setOn(consentRequired);
+    }
+
+    public String getConsentText() {
+        return getInputValue(consentTextElement);
+    }
+
+    public void setConsentText(String consentText) {
+        setInputValue(consentTextElement, consentText);
+    }
+
+    public String getMapperType() {
+        return mapperTypeSelect.getFirstSelectedOption().getText();
+    }
+
+    public void setMapperType(String type) {
+        mapperTypeSelect.selectByVisibleText(type);
+    }
+    
+    public String getProperty() {
+        return getInputValue(propertyInput);
+    }
+    
+    public void setProperty(String value) {
+        setInputValue(propertyInput, value);
+    }
+
+    public String getUserAttribute() {
+        return getInputValue(userAttributeInput);
+    }
+
+    public void setUserAttribute(String value) {
+        setInputValue(userAttributeInput, value);
+    }
+
+    public String getUserSessionNote() {
+        return getInputValue(userSessionNoteInput);
+    }
+
+    public void setUserSessionNote(String value) {
+        setInputValue(userSessionNoteInput, value);
+    }
+
+    public boolean isMultivalued() {
+        return multivaluedInput.isOn();
+    }
+
+    public void setMultivalued(boolean value) {
+        multivaluedInput.setOn(value);
+    }
+
+    public String getRole() {
+        return getInputValue(roleInput);
+    }
+
+    public void setRole(String value) {
+        setInputValue(roleInput, value);
+    }
+
+    public String getNewRole() {
+        return getInputValue(newRoleInput);
+    }
+
+    public void setNewRole(String value) {
+        setInputValue(newRoleInput, value);
+    }
+
+    public String getTokenClaimName() {
+        return getInputValue(tokenClaimNameInput);
+    }
+
+    public void setTokenClaimName(String value) {
+        setInputValue(tokenClaimNameInput, value);
+    }
+
+    public String getTokenClaimValue() {
+        return getInputValue(tokenClaimValueInput);
+    }
+
+    public void setTokenClaimValue(String value) {
+        setInputValue(tokenClaimValueInput, value);
+    }
+
+    public String getClaimJSONType() {
+        return claimJSONTypeInput.getFirstSelectedOption().getText();
+    }
+
+    public void setClaimJSONType(String value) {
+        claimJSONTypeInput.selectByVisibleText(value);
+    }
+
+    public boolean isAddToIDToken() {
+        return addToIDTokenInput.isOn();
+    }
+
+    public void setAddToIDToken(boolean value) {
+        addToIDTokenInput.setOn(value);
+    }
+
+    public boolean isAddToAccessToken() {
+        return addToAccessTokenInput.isOn();
+    }
+
+    public void setAddToAccessToken(boolean value) {
+        addToAccessTokenInput.setOn(value);
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/CreateKerberosUserProvider.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/CreateKerberosUserProvider.java
new file mode 100644
index 0000000..6347392
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/CreateKerberosUserProvider.java
@@ -0,0 +1,28 @@
+package org.keycloak.testsuite.console.page.federation;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.testsuite.console.page.AdminConsoleCreate;
+
+/**
+ *
+ * @author pdrozd
+ */
+public class CreateKerberosUserProvider extends AdminConsoleCreate {
+
+    @Page
+    private KerberosUserProviderForm form;
+
+    public CreateKerberosUserProvider() {
+        setEntity("user-federation");
+    }
+
+    @Override
+    public String getUriFragment() {
+        return super.getUriFragment() + "/providers/kerberos";
+    }
+
+    public KerberosUserProviderForm form() {
+        return form;
+    }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/CreateLdapUserProvider.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/CreateLdapUserProvider.java
index 4dc47f9..13ba716 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/CreateLdapUserProvider.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/CreateLdapUserProvider.java
@@ -1,5 +1,6 @@
 package org.keycloak.testsuite.console.page.federation;
 
+import org.jboss.arquillian.graphene.page.Page;
 import org.keycloak.testsuite.console.page.AdminConsoleCreate;
 
 /**
@@ -8,6 +9,9 @@ import org.keycloak.testsuite.console.page.AdminConsoleCreate;
  */
 public class CreateLdapUserProvider extends AdminConsoleCreate {
 
+    @Page
+    private LdapUserProviderForm form;
+
     public CreateLdapUserProvider() {
         setEntity("user-federation");
     }
@@ -17,4 +21,7 @@ public class CreateLdapUserProvider extends AdminConsoleCreate {
         return super.getUriFragment() + "/providers/ldap";
     }
 
+    public LdapUserProviderForm form() {
+        return form;
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/KerberosUserProviderForm.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/KerberosUserProviderForm.java
new file mode 100644
index 0000000..1fb068f
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/KerberosUserProviderForm.java
@@ -0,0 +1,81 @@
+package org.keycloak.testsuite.console.page.federation;
+
+import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
+
+import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
+import org.keycloak.testsuite.page.Form;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+import org.openqa.selenium.support.ui.Select;
+
+/**
+ * @author pdrozd
+ */
+public class KerberosUserProviderForm extends Form {
+
+    @FindBy(id = "consoleDisplayName")
+    private WebElement consoleDisplayNameInput;
+
+    @FindBy(id = "priority")
+    private WebElement priorityInput;
+
+    @FindBy(id = "kerberosRealm")
+    private WebElement kerberosRealmInput;
+
+    @FindBy(id = "serverPrincipal")
+    private WebElement serverPrincipalInput;
+
+    @FindBy(id = "keyTab")
+    private WebElement keyTabInput;
+
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='debug']]")
+    private OnOffSwitch debug;
+
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='allowPasswordAuthentication']]")
+    private OnOffSwitch allowPwdAuth;
+
+    @FindBy(id = "editMode")
+    private Select editModeSelect;
+
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='updateProfileFirstLogin']]")
+    private OnOffSwitch updateProfileFirstLogin;
+
+    public void setConsoleDisplayNameInput(String name) {
+        setInputValue(consoleDisplayNameInput, name);
+    }
+
+    public void setPriorityInput(Integer priority) {
+        setInputValue(priorityInput, String.valueOf(priority));
+    }
+
+    public void setKerberosRealmInput(String kerberosRealm) {
+        waitGuiForElement(By.id("kerberosRealm"));
+        setInputValue(kerberosRealmInput, kerberosRealm);
+    }
+
+    public void setServerPrincipalInput(String serverPrincipal) {
+        setInputValue(serverPrincipalInput, serverPrincipal);
+    }
+
+    public void setKeyTabInput(String keyTab) {
+        setInputValue(keyTabInput, keyTab);
+    }
+
+    public void setDebugEnabled(boolean debugEnabled) {
+        this.debug.setOn(debugEnabled);
+    }
+
+    public void setAllowPasswordAuthentication(boolean enabled) {
+        allowPwdAuth.setOn(enabled);
+    }
+
+    public void selectEditMode(String mode) {
+        waitGuiForElement(By.id("editMode"));
+        editModeSelect.selectByVisibleText(mode);
+    }
+
+    public void setUpdateProfileFirstLogin(boolean enabled) {
+        updateProfileFirstLogin.setOn(enabled);
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/LdapUserProviderForm.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/LdapUserProviderForm.java
index a9b8882..3acc5ec 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/LdapUserProviderForm.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/federation/LdapUserProviderForm.java
@@ -1,5 +1,8 @@
 package org.keycloak.testsuite.console.page.federation;
 
+import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
+import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
+
 import org.jboss.arquillian.graphene.findby.FindByJQuery;
 import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
 import org.keycloak.testsuite.page.Form;
@@ -8,10 +11,8 @@ import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
 import org.openqa.selenium.support.ui.Select;
 
-import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
-
 /**
- * Created by fkiss.
+ * @author fkiss, pdrozd
  */
 public class LdapUserProviderForm extends Form {
 
@@ -24,24 +25,33 @@ public class LdapUserProviderForm extends Form {
     @FindBy(id = "usernameLDAPAttribute")
     private WebElement usernameLDAPAttributeInput;
 
+    @FindBy(id = "rdnLDAPAttribute")
+    private WebElement rdnLDAPAttributeInput;
+
+    @FindBy(id = "uuidLDAPAttribute")
+    private WebElement uuidLDAPAttributeInput;
+
     @FindBy(id = "userObjectClasses")
     private WebElement userObjectClassesInput;
 
     @FindBy(id = "ldapConnectionUrl")
     private WebElement ldapConnectionUrlInput;
 
-    @FindBy(id = "ldapBaseDn")
-    private WebElement ldapBaseDnInput;
-
     @FindBy(id = "ldapUsersDn")
     private WebElement ldapUserDnInput;
 
+    @FindBy(id = "authType")
+    private Select authTypeSelect;
+
     @FindBy(id = "ldapBindDn")
     private WebElement ldapBindDnInput;
 
     @FindBy(id = "ldapBindCredential")
     private WebElement ldapBindCredentialInput;
 
+    @FindBy(id = "searchScope")
+    private Select searchScopeSelect;
+
     @FindBy(id = "kerberosRealm")
     private WebElement kerberosRealmInput;
 
@@ -72,59 +82,173 @@ public class LdapUserProviderForm extends Form {
     @FindByJQuery("a:contains('Test authentication')")
     private WebElement testAuthenticationButton;
 
-    @FindByJQuery("div[class='onoffswitch']:eq(0)")
+    @FindByJQuery("a:contains('Synchronize changed users')")
+    private WebElement synchronizeChangedUsersButton;
+
+    @FindByJQuery("button:contains('Synchronize all users')")
+    private WebElement synchronizeAllUsersButton;
+
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='syncRegistrations']]")
     private OnOffSwitch syncRegistrations;
 
-    @FindByJQuery("div[class='onoffswitch']:eq(1)")
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='connectionPooling']]")
     private OnOffSwitch connectionPooling;
 
-    @FindByJQuery("div[class='onoffswitch']:eq(2)")
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='pagination']]")
     private OnOffSwitch pagination;
 
-    @FindByJQuery("div[class='onoffswitch']:eq(3)")
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='userAccountControlsAfterPasswordUpdate']]")
+    private OnOffSwitch enableAccountAfterPasswordUpdate;
+
+    @FindBy(xpath = "//div[contains(@class,'onoffswitch') and ./input[@id='allowKerberosAuthentication']]")
     private OnOffSwitch allowKerberosAuth;
 
-    @FindByJQuery("div[class='onoffswitch']:eq(4)")
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='debug']]")
     private OnOffSwitch debug;
 
-    @FindByJQuery("div[class='onoffswitch']:eq(5)")
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='useKerberosForPasswordAuthentication']]")
     private OnOffSwitch useKerberosForPwdAuth;
 
-    @FindByJQuery("div[class='onoffswitch']:eq(6)")
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='compositeSwitch']]")
     private OnOffSwitch periodicFullSync;
 
-    @FindByJQuery("div[class='onoffswitch']:eq(7)")
+    @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='changedSyncEnabled']]")
     private OnOffSwitch periodicChangedUsersSync;
 
-    @FindByJQuery("button:contains('Save')")
-    private WebElement saveButton;
+    public void setConsoleDisplayNameInput(String name) {
+        setInputValue(consoleDisplayNameInput, name);
+    }
+
+    public void setPriorityInput(Integer priority) {
+        setInputValue(priorityInput, String.valueOf(priority));
+    }
+
+    public void setUsernameLDAPAttributeInput(String usernameLDAPAttribute) {
+        setInputValue(usernameLDAPAttributeInput, usernameLDAPAttribute);
+    }
+
+    public void setRdnLDAPAttributeInput(String rdnLDAPAttribute) {
+        setInputValue(rdnLDAPAttributeInput, rdnLDAPAttribute);
+    }
+
+    public void setUuidLDAPAttributeInput(String uuidLDAPAttribute) {
+        setInputValue(uuidLDAPAttributeInput, uuidLDAPAttribute);
+    }
+
+    public void setUserObjectClassesInput(String userObjectClasses) {
+        setInputValue(userObjectClassesInput, userObjectClasses);
+    }
+
+    public void setLdapConnectionUrlInput(String ldapConnectionUrl) {
+        setInputValue(ldapConnectionUrlInput, ldapConnectionUrl);
+    }
+
+    public void setLdapUserDnInput(String ldapUserDn) {
+        setInputValue(ldapUserDnInput, ldapUserDn);
+    }
+
+    public void setLdapBindDnInput(String ldapBindDn) {
+        setInputValue(ldapBindDnInput, ldapBindDn);
+    }
+
+    public void setLdapBindCredentialInput(String ldapBindCredential) {
+        setInputValue(ldapBindCredentialInput, ldapBindCredential);
+    }
+
+    public void setKerberosRealmInput(String kerberosRealm) {
+        waitAjaxForElement(kerberosRealmInput);
+        setInputValue(kerberosRealmInput, kerberosRealm);
+    }
+
+    public void setServerPrincipalInput(String serverPrincipal) {
+        waitAjaxForElement(serverPrincipalInput);
+        setInputValue(serverPrincipalInput, serverPrincipal);
+    }
+
+    public void setKeyTabInput(String keyTab) {
+        waitAjaxForElement(keyTabInput);
+        setInputValue(keyTabInput, keyTab);
+    }
+
+    public void setBatchSizeForSyncInput(String batchSizeForSync) {
+        setInputValue(batchSizeForSyncInput, batchSizeForSync);
+    }
 
-    public void selectEditMode(String mode){
+    public void selectEditMode(String mode) {
         waitGuiForElement(By.id("editMode"));
         editModeSelect.selectByVisibleText(mode);
     }
 
-    public void selectVendor(String vendor){
-        waitGuiForElement(By.id("editMode"));
+    public void selectVendor(String vendor) {
+        waitGuiForElement(By.id("vendor"));
         vendorSelect.selectByVisibleText(vendor);
     }
 
-    public void configureLdap(String displayName, String editMode, String vendor, String connectionUrl, String userDN, String ldapBindDn, String ldapBindCredential){
-        consoleDisplayNameInput.sendKeys(displayName);
-        editModeSelect.selectByVisibleText(editMode);
-        selectVendor(vendor);
-        ldapConnectionUrlInput.sendKeys(connectionUrl);
-        ldapUserDnInput.sendKeys(userDN);
-        ldapBindDnInput.sendKeys(ldapBindDn);
-        ldapBindCredentialInput.sendKeys(ldapBindCredential);
-        saveButton.click();
+    public void selectAuthenticationType(String authenticationType) {
+        waitGuiForElement(By.id("authType"));
+        authTypeSelect.selectByVisibleText(authenticationType);
+    }
+
+    public void selectSearchScope(String searchScope) {
+        waitGuiForElement(By.id("searchScope"));
+        searchScopeSelect.selectByVisibleText(searchScope);
+    }
+
+    public void setSyncRegistrationsEnabled(boolean syncRegistrationsEnabled) {
+        this.syncRegistrations.setOn(syncRegistrationsEnabled);
+    }
+
+    public void setConnectionPoolingEnabled(boolean connectionPoolingEnabled) {
+        this.connectionPooling.setOn(connectionPoolingEnabled);
     }
 
-    public void testConnection(){
+    public void setPaginationEnabled(boolean paginationEnabled) {
+        this.pagination.setOn(paginationEnabled);
+    }
+
+    public void setAccountAfterPasswordUpdateEnabled(boolean enabled) {
+        if ((!enableAccountAfterPasswordUpdate.isOn() && enabled)
+                || !enabled && enableAccountAfterPasswordUpdate.isOn()) {
+            driver.findElement(By
+                    .xpath("//div[contains(@class,'onoffswitch') and ./input[@id='userAccountControlsAfterPasswordUpdate']]"))
+                    .findElements(By.tagName("span")).get(0).click();
+        }
+    }
+
+    public void setAllowKerberosAuthEnabled(boolean enabled) {
+        if ((!allowKerberosAuth.isOn() && enabled) || !enabled && allowKerberosAuth.isOn()) {
+            driver.findElement(
+                    By.xpath("//div[contains(@class,'onoffswitch') and ./input[@id='allowKerberosAuthentication']]"))
+                    .findElements(By.tagName("span")).get(0).click();
+        }
+    }
+
+    public void setDebugEnabled(boolean debugEnabled) {
+        this.debug.setOn(debugEnabled);
+    }
+
+    public void setUseKerberosForPwdAuthEnabled(boolean useKerberosForPwdAuthEnabled) {
+        this.useKerberosForPwdAuth.setOn(useKerberosForPwdAuthEnabled);
+    }
+
+    public void setPeriodicFullSyncEnabled(boolean periodicFullSyncEnabled) {
+        this.periodicFullSync.setOn(periodicFullSyncEnabled);
+    }
+
+    public void setPeriodicChangedUsersSyncEnabled(boolean periodicChangedUsersSyncEnabled) {
+        this.periodicChangedUsersSync.setOn(periodicChangedUsersSyncEnabled);
+    }
+
+    public void testConnection() {
         testConnectionButton.click();
     }
 
-    public void testAuthentication(){
+    public void testAuthentication() {
         testAuthenticationButton.click();
     }
+
+    public void synchronizeAllUsers() {
+        waitAjaxForElement(synchronizeAllUsersButton);
+        synchronizeAllUsersButton.click();
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java
index 6319c4c..118e058 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java
@@ -36,6 +36,14 @@ public class OnOffSwitch {
     @ArquillianResource
     private Actions actions;
 
+    public OnOffSwitch() {
+    }
+
+    public OnOffSwitch(WebElement root, Actions actions) {
+        this.root = root;
+        this.actions = actions;
+    }
+
     public boolean isOn() {
         waitAjaxForElement(root);
         return root.findElement(By.tagName("input")).isSelected();
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java
index ac6ed22..7b0fdb1 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java
@@ -41,6 +41,11 @@ public final class WaitUtils {
                 .element(element).is().not().present();
     }
 
+    public static void waitAjaxForElementNotVisible(WebElement element) {
+        waitAjax().until()
+                .element(element).is().not().visible();
+    }
+
     public static void waitGuiForElement(By element, String message) {
         waitGui().until(message)
                 .element(element).is().present();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/authentication/OTPPolicyTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/authentication/OTPPolicyTest.java
index 72455e2..d9f8f89 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/authentication/OTPPolicyTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/authentication/OTPPolicyTest.java
@@ -24,6 +24,7 @@ package org.keycloak.testsuite.console.authentication;
 import org.jboss.arquillian.graphene.page.Page;
 import static org.junit.Assert.*;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.console.AbstractConsoleTest;
@@ -66,42 +67,58 @@ public class OTPPolicyTest extends AbstractConsoleTest {
     }      
     
     @Test
+    @Ignore //KEYCLOAK-2051 when you close notification, it is not displayed again
     public void invalidValuesTest() {
         otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "", "30");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
+        otpPolicyPage.closeNotification();
+        otpPolicyPage.navigateTo();// workaround: input.clear() doesn't work when <input type="number" ...
         
         otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, " ", "30");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
+        otpPolicyPage.closeNotification();
+        otpPolicyPage.navigateTo();
         
         otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "no number", "30");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
+        otpPolicyPage.closeNotification();
+        otpPolicyPage.navigateTo();
         
         RealmRepresentation realm = testRealmResource().toRepresentation();
         assertEquals(Integer.valueOf(1), realm.getOtpPolicyLookAheadWindow());
 
         otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
+        otpPolicyPage.closeNotification();
+        otpPolicyPage.navigateTo();
         
         otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", " ");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
+        otpPolicyPage.closeNotification();
+        otpPolicyPage.navigateTo();
         
         otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "no number");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
-
+        otpPolicyPage.closeNotification();
+        otpPolicyPage.navigateTo();
+        
         realm = testRealmResource().toRepresentation();
         assertEquals(Integer.valueOf(30), realm.getOtpPolicyPeriod());
         
         otpPolicyPage.form().setValues(OTPType.COUNTER_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
+        otpPolicyPage.closeNotification();
+        otpPolicyPage.navigateTo();
         
         otpPolicyPage.form().setValues(OTPType.COUNTER_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", " ");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
+        otpPolicyPage.closeNotification();
+        otpPolicyPage.navigateTo();
         
         otpPolicyPage.form().setValues(OTPType.COUNTER_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "no number");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
-        
-        otpPolicyPage.form().setValues(OTPType.COUNTER_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "1", "1 2");
-        assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());
+        otpPolicyPage.closeNotification();
+        otpPolicyPage.navigateTo();
         
         realm = testRealmResource().toRepresentation();
         assertEquals(Integer.valueOf(0), realm.getOtpPolicyInitialCounter());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/federation/KerberosUserFederationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/federation/KerberosUserFederationTest.java
new file mode 100644
index 0000000..47521e5
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/federation/KerberosUserFederationTest.java
@@ -0,0 +1,75 @@
+package org.keycloak.testsuite.console.federation;
+
+import static org.junit.Assert.assertEquals;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.junit.Test;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserFederationProviderRepresentation;
+import org.keycloak.testsuite.console.AbstractConsoleTest;
+import org.keycloak.testsuite.console.page.federation.CreateKerberosUserProvider;
+
+/**
+ * @author pdrozd
+ */
+public class KerberosUserFederationTest extends AbstractConsoleTest {
+
+	private static final String UNSYNCED = "UNSYNCED";
+
+	private static final String READ_ONLY = "READ_ONLY";
+
+	@Page
+	private CreateKerberosUserProvider createKerberosUserProvider;
+
+	@Test
+	public void configureKerberosProvider() {
+		createKerberosUserProvider.navigateTo();
+		createKerberosUserProvider.form().setConsoleDisplayNameInput("kerberos");
+		createKerberosUserProvider.form().setKerberosRealmInput("KEYCLOAK.ORG");
+		createKerberosUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");
+		createKerberosUserProvider.form().setKeyTabInput("http.keytab");
+		createKerberosUserProvider.form().setDebugEnabled(true);
+		createKerberosUserProvider.form().setAllowPasswordAuthentication(true);
+		createKerberosUserProvider.form().selectEditMode(READ_ONLY);
+		createKerberosUserProvider.form().setUpdateProfileFirstLogin(true);
+		createKerberosUserProvider.form().save();
+		assertFlashMessageSuccess();
+		RealmRepresentation realm = testRealmResource().toRepresentation();
+		UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
+		assertKerberosSetings(ufpr, "KEYCLOAK.ORG", "HTTP/localhost@KEYCLOAK.ORG", "http.keytab", "true", "true", "true");
+	}
+
+	@Test
+	public void invalidSettingsTest() {
+		createKerberosUserProvider.navigateTo();
+		createKerberosUserProvider.form().setConsoleDisplayNameInput("kerberos");
+		createKerberosUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");
+		createKerberosUserProvider.form().setKeyTabInput("http.keytab");
+		createKerberosUserProvider.form().setDebugEnabled(true);
+		createKerberosUserProvider.form().setAllowPasswordAuthentication(true);
+		createKerberosUserProvider.form().selectEditMode(UNSYNCED);
+		createKerberosUserProvider.form().setUpdateProfileFirstLogin(true);
+		createKerberosUserProvider.form().save();
+		assertFlashMessageDanger();
+		createKerberosUserProvider.form().setServerPrincipalInput("");
+		createKerberosUserProvider.form().setKerberosRealmInput("KEYCLOAK.ORG");;
+		createKerberosUserProvider.form().save();
+		assertFlashMessageDanger();
+		createKerberosUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");;
+		createKerberosUserProvider.form().setKeyTabInput("");
+		createKerberosUserProvider.form().save();
+		assertFlashMessageDanger();		
+		createKerberosUserProvider.form().setKeyTabInput("http.keytab");;
+		createKerberosUserProvider.form().save();
+		assertFlashMessageSuccess();
+	}
+
+	private void assertKerberosSetings(UserFederationProviderRepresentation ufpr, String kerberosRealm, String serverPrincipal, String keyTab, String debug, String useKerberosForPasswordAuthentication, String updateProfileFirstLogin) {
+		assertEquals(kerberosRealm, ufpr.getConfig().get("kerberosRealm"));
+		assertEquals(serverPrincipal, ufpr.getConfig().get("serverPrincipal"));
+		assertEquals(keyTab, ufpr.getConfig().get("keyTab"));
+		assertEquals(debug, ufpr.getConfig().get("debug"));
+		assertEquals(useKerberosForPasswordAuthentication, ufpr.getConfig().get("allowKerberosAuthentication"));
+		assertEquals(updateProfileFirstLogin, ufpr.getConfig().get("updateProfileFirstLogin"));
+	}
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/federation/LdapUserFederationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/federation/LdapUserFederationTest.java
index e70da46..e040362 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/federation/LdapUserFederationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/federation/LdapUserFederationTest.java
@@ -1,71 +1,192 @@
 package org.keycloak.testsuite.console.federation;
 
-import org.jboss.arquillian.graphene.page.Page;
-import org.junit.*;
-import org.keycloak.models.LDAPConstants;
-
-import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.testsuite.console.AbstractConsoleTest;
-import org.keycloak.testsuite.console.page.federation.LdapUserProviderForm;
-import org.keycloak.testsuite.console.page.federation.UserFederation;
-import org.keycloak.testsuite.console.page.users.Users;
-import org.keycloak.testsuite.util.LDAPTestConfiguration;
+import static org.junit.Assert.assertEquals;
 
-import java.util.Map;
+import java.util.Properties;
 
-import static org.junit.Assert.assertTrue;
-import static org.keycloak.representations.idm.CredentialRepresentation.PASSWORD;
-import static org.keycloak.testsuite.admin.Users.setPasswordFor;
+import org.jboss.arquillian.graphene.page.Page;
+import org.junit.Test;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserFederationProviderRepresentation;
+import org.keycloak.testsuite.console.AbstractConsoleTest;
+import org.keycloak.testsuite.console.page.federation.CreateLdapUserProvider;
+import org.keycloak.util.ldap.LDAPEmbeddedServer;
 
 /**
- * Created by fkiss.
+ * @author fkiss, pdrozd
  */
 public class LdapUserFederationTest extends AbstractConsoleTest {
 
-    @Page
-    private LdapUserProviderForm ldapUserProviderForm;
+    private static final String UNSYNCED = "UNSYNCED";
 
-    @Page
-    private UserFederation userFederationPage;
+    private static final String READ_ONLY = "READ_ONLY";
+
+    private static final String RED_HAT_DIRECTORY_SERVER = "Red Hat Directory Server";
+
+    private static final String WRITABLE = "WRITABLE";
+
+    private static final String ACTIVE_DIRECTORY = "Active Directory";
 
     @Page
-    private Users usersPage;
+    private CreateLdapUserProvider createLdapUserProvider;
 
-    @Before
-    public void beforeTestLdapUserFederation() {
-        //configure().userFederation();
+    @Test
+    public void configureAdProvider() {
+        createLdapUserProvider.navigateTo();
+        createLdapUserProvider.form().selectVendor(ACTIVE_DIRECTORY);
+        createLdapUserProvider.form().setConsoleDisplayNameInput("ldap");
+        createLdapUserProvider.form().selectEditMode(WRITABLE);
+        createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:389");
+        createLdapUserProvider.form().setLdapBindDnInput("KEYCLOAK/Administrator");
+        createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
+        createLdapUserProvider.form().setLdapBindCredentialInput("secret");
+        createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(false);
+        // enable kerberos
+        createLdapUserProvider.form().setAllowKerberosAuthEnabled(true);
+        createLdapUserProvider.form().setKerberosRealmInput("KEYCLOAK.ORG");
+        createLdapUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");
+        createLdapUserProvider.form().setKeyTabInput("http.keytab");
+        createLdapUserProvider.form().setDebugEnabled(true);
+        createLdapUserProvider.form().save();
+        assertFlashMessageSuccess();
+
+        RealmRepresentation realm = testRealmResource().toRepresentation();
+        UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
+        assertLdapProviderSetting(ufpr, "ldap", 0, WRITABLE, "false", "ad", "1", "true", "true", "false");
+        assertLdapBasicMapping(ufpr, "cn", "cn", "objectGUID", "person, organizationalPerson, user",
+                "ou=People,dc=keycloak,dc=org");
+        assertLdapSyncSetings(ufpr, "1000", 0, 0);
+        assertLdapKerberosSetings(ufpr, "KEYCLOAK.ORG", "HTTP/localhost@KEYCLOAK.ORG", "http.keytab", "true", "false");
     }
 
-    @Ignore
     @Test
-    public void addAndConfigureProvider() {
-        adminConsolePage.navigateTo();
-        testRealmLoginPage.form().login(testUser);
+    public void configureRhdsProvider() {
+        createLdapUserProvider.navigateTo();
+        createLdapUserProvider.form().selectVendor(RED_HAT_DIRECTORY_SERVER);
+        createLdapUserProvider.form().setConsoleDisplayNameInput("ldap");
+        createLdapUserProvider.form().selectEditMode(READ_ONLY);
+        createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:389");
+        createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
+        createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
+        createLdapUserProvider.form().setLdapBindCredentialInput("secret");
+        createLdapUserProvider.form().save();
+        assertFlashMessageSuccess();
+
+        RealmRepresentation realm = testRealmResource().toRepresentation();
+        UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
+        assertLdapProviderSetting(ufpr, "ldap", 0, READ_ONLY, "false", "rhds", "1", "true", "true", "true");
+        assertLdapBasicMapping(ufpr, "uid", "uid", "nsuniqueid", "inetOrgPerson, organizationalPerson",
+                "ou=People,dc=keycloak,dc=org");
+        assertLdapSyncSetings(ufpr, "1000", 0, 0);
+    }
 
-        String name = "ldapname";
+    @Test
+    public void invalidSettingsTest() {
+        createLdapUserProvider.navigateTo();
+        createLdapUserProvider.form().selectVendor(ACTIVE_DIRECTORY);
+        createLdapUserProvider.form().setConsoleDisplayNameInput("ldap");
+        createLdapUserProvider.form().selectEditMode(UNSYNCED);
+        createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
+        createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
+        createLdapUserProvider.form().setLdapBindCredentialInput("secret");
+        createLdapUserProvider.form().save();
+        assertFlashMessageDanger();
+        createLdapUserProvider.form().setLdapUserDnInput("");
+        createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:389");
+        createLdapUserProvider.form().save();
+        assertFlashMessageDanger();
+        createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
+        createLdapUserProvider.form().setLdapBindDnInput("");
+        createLdapUserProvider.form().save();
+        assertFlashMessageDanger();
+        createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
+        createLdapUserProvider.form().setLdapBindCredentialInput("");
+        createLdapUserProvider.form().save();
+        assertFlashMessageDanger();
+        createLdapUserProvider.form().setLdapBindCredentialInput("secret");
+        createLdapUserProvider.form().save();
+        assertFlashMessageSuccess();
+    }
+
+    @Test
+    public void testConnection() throws Exception {
+        createLdapUserProvider.navigateTo();
+        createLdapUserProvider.form().selectVendor("Other");
+        createLdapUserProvider.form().setConsoleDisplayNameInput("ldap");
+        createLdapUserProvider.form().selectEditMode(WRITABLE);
+        createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:10389");
+        createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
+        createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
+        createLdapUserProvider.form().setLdapBindCredentialInput("secret");
+        createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(true);
+        createLdapUserProvider.form().save();
+        assertFlashMessageSuccess();
+        LDAPEmbeddedServer ldapServer = null;
+        try {
+            ldapServer = startEmbeddedLdapServer();
+            createLdapUserProvider.form().testConnection();
+            assertFlashMessageSuccess();
+            createLdapUserProvider.form().testAuthentication();
+            assertFlashMessageSuccess();
+            createLdapUserProvider.form().synchronizeAllUsers();
+            assertFlashMessageSuccess();
+            createLdapUserProvider.form().setLdapBindCredentialInput("secret1");
+            createLdapUserProvider.form().testAuthentication();
+            assertFlashMessageDanger();
+        } finally {
+            if (ldapServer != null) {
+                ldapServer.stop();
+            }
+        }
+    }
 
-        String LDAP_CONNECTION_PROPERTIES_LOCATION = "ldap/ldap-connection.properties";
-        LDAPTestConfiguration ldapTestConfiguration = LDAPTestConfiguration.readConfiguration(LDAP_CONNECTION_PROPERTIES_LOCATION);
+    private void assertLdapProviderSetting(UserFederationProviderRepresentation ufpr, String name, int priority,
+            String editMode, String syncRegistrations, String vendor, String searchScope, String connectionPooling,
+            String pagination, String enableAccountAfterPasswordUpdate) {
+        assertEquals(name, ufpr.getDisplayName());
+        assertEquals(priority, ufpr.getPriority());
+        assertEquals(editMode, ufpr.getConfig().get("editMode"));
+        assertEquals(syncRegistrations, ufpr.getConfig().get("syncRegistrations"));
+        assertEquals(vendor, ufpr.getConfig().get("vendor"));
+        assertEquals(searchScope, ufpr.getConfig().get("searchScope"));
+        assertEquals(connectionPooling, ufpr.getConfig().get("connectionPooling"));
+        assertEquals(pagination, ufpr.getConfig().get("pagination"));
+        assertEquals(enableAccountAfterPasswordUpdate, ufpr.getConfig().get("userAccountControlsAfterPasswordUpdate"));
+    }
 
-        UserRepresentation newUser = new UserRepresentation();
-        String testUsername = "defaultrole tester";
-        newUser.setUsername(testUsername);
-        setPasswordFor(newUser, PASSWORD);
+    private void assertLdapBasicMapping(UserFederationProviderRepresentation ufpr, String usernameLdapAttribute,
+            String rdnLdapAttr, String uuidLdapAttr, String userObjectClasses, String userDN) {
+        assertEquals(usernameLdapAttribute, ufpr.getConfig().get("usernameLDAPAttribute"));
+        assertEquals(rdnLdapAttr, ufpr.getConfig().get("rdnLDAPAttribute"));
+        assertEquals(uuidLdapAttr, ufpr.getConfig().get("uuidLDAPAttribute"));
+        assertEquals(userObjectClasses, ufpr.getConfig().get("userObjectClasses"));
+        assertEquals(userDN, ufpr.getConfig().get("usersDn"));
+    }
 
-        Map<String,String> ldapConfig = ldapTestConfiguration.getLDAPConfig();
+    private void assertLdapKerberosSetings(UserFederationProviderRepresentation ufpr, String kerberosRealm,
+            String serverPrincipal, String keyTab, String debug, String useKerberosForPasswordAuthentication) {
+        assertEquals(kerberosRealm, ufpr.getConfig().get("kerberosRealm"));
+        assertEquals(serverPrincipal, ufpr.getConfig().get("serverPrincipal"));
+        assertEquals(keyTab, ufpr.getConfig().get("keyTab"));
+        assertEquals(debug, ufpr.getConfig().get("debug"));
+        assertEquals(useKerberosForPasswordAuthentication,
+                ufpr.getConfig().get("useKerberosForPasswordAuthentication"));
+    }
 
-        //addLdapProviderTest
-        configure().userFederation();
-        userFederationPage.addProvider("ldap");
-        ldapUserProviderForm.configureLdap(ldapConfig.get(LDAPConstants.LDAP_PROVIDER), ldapConfig.get(LDAPConstants.EDIT_MODE), ldapConfig.get(LDAPConstants.VENDOR), ldapConfig.get(LDAPConstants.CONNECTION_URL), ldapConfig.get(LDAPConstants.USERS_DN), ldapConfig.get(LDAPConstants.BIND_DN), ldapConfig.get(LDAPConstants.BIND_CREDENTIAL));
+    private void assertLdapSyncSetings(UserFederationProviderRepresentation ufpr, String batchSize,
+            int periodicFullSync, int periodicChangedUsersSync) {
+        assertEquals(batchSize, ufpr.getConfig().get("batchSizeForSync"));
+        assertEquals(periodicFullSync, ufpr.getFullSyncPeriod());
+        assertEquals(periodicChangedUsersSync, ufpr.getChangedSyncPeriod());
     }
 
-    @Ignore
-    @Test
-    public void caseSensitiveSearch() {
-        // This should fail for now due to case-sensitivity
-        adminConsolePage.navigateTo();
-        testRealmLoginPage.form().login("johnKeycloak", "Password1");
-        assertTrue(flashMessage.getText(), flashMessage.isDanger());
+    private LDAPEmbeddedServer startEmbeddedLdapServer() throws Exception {
+        Properties defaultProperties = new Properties();
+        defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_DSF, LDAPEmbeddedServer.DSF_INMEMORY);
+        defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_LDIF_FILE, "classpath:ldap/users.ldif");
+        LDAPEmbeddedServer ldapEmbeddedServer = new LDAPEmbeddedServer(defaultProperties);
+        ldapEmbeddedServer.init();
+        ldapEmbeddedServer.start();
+        return ldapEmbeddedServer;
     }
-}
\ No newline at end of file
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/ldap/users.ldif b/testsuite/integration-arquillian/tests/base/src/test/resources/ldap/users.ldif
new file mode 100644
index 0000000..176e19b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/ldap/users.ldif
@@ -0,0 +1,20 @@
+dn: dc=keycloak,dc=org
+objectclass: dcObject
+objectclass: organization
+o: Keycloak
+dc: Keycloak
+
+dn: ou=People,dc=keycloak,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: People
+
+dn: ou=RealmRoles,dc=keycloak,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: RealmRoles
+
+dn: ou=FinanceRoles,dc=keycloak,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: FinanceRoles